Fast SQL query but slow result retrieval

Use some buffer based class such as TStringStream to populate the string. this will avoid slow reallocation of String concatenation (s := s + foo).

Don't use aADSQuery.FieldbyName('Name').AsString in the loop. It's slow. Instead create a local variable F like this:

var
  F: TField;

F := aADSQuery.FieldbyName('Name');
for i:=0 to count-1 do
begin
  aADSQuery.RecNo := i;
  F.AsString; 
end;

I believe using aADSQuery.Next is faster than using RecNo

procedure Test;
var
  F: TField;
  Buf: TStringStream;
  S: string;
begin
  aADSQuery.DisableControls;
  try
    aADSQuery.Open;
    F := aADSQuery.FieldbyName('Name');
    Buf := TStringStream.Create('');
    try
      while not aADSQuery.Eof do
      begin
        Buf.WriteString(F.AsString + ',');
        aADSQuery.Next;
      end;
      S := Buf.DataString;
    finally
      Buf.Free;
    end;
  finally
    aADSQuery.EnableControls;
  end;
end;

You can generate that string on the server side and return it to the client side without the need to construct any strings on the client side:

DECLARE @Names NVARCHAR(max)
SELECT @Names = ''
SELECT @Names = @Names + ',' + ISNULL([Name], '') FROM MyTable
SELECT @Names

Also you could optimize performance by setting TAdsQuery.AdsTableOptions. Make sure AdsFilterOptions is set to IGNORE_WHEN_COUNTING and AdsFreshRecordCount is set to False.


From the OP, it is not entirely clear to me if the goal is to find the total number of records or to display the data to a user. If it is to display the data, then appending all the data for 55,000 records into a single string is probably not the best approach. If you are happy with the performance of running the query in Advantage Data Architect, then it probably makes sense to use the similar approach and store the data in some kind of grid.

For example, associate a TDataSource with a TDBGrid and bind the query to the data source:

AdsQuery1.Open;
DataSource1.DataSet:=AdsQuery1;
DBGrid1.DataSource:=DataSource1;

The data aware grid will only fetch as much data as is needed to fill the grid and will request data on demand as the user pages through it.

Edit When you request the record count, the entire result set has to be resolved by the server. If you are using Advantage Local Server and if the data resides on a network server, then there will be extra cost involved in reading all of the data across the network. If you are using Advantage Database Server (the client/server version), then the processing will take place at the server and may be much faster.

It of course depends on the query, but 9 seconds to resolve the result set might be overly long. Within Advantage Data Architect, you can check the optimization of the query. There is a "Show Plan" option under the SQL menu as well as a button on the tool bar in the SQL utility for showing the query plan. It may be that you are missing a necessary index.