BDE vs ADO in Delphi

后端 未结 3 1713
一向
一向 2020-12-13 21:50

Please note the Edit below for a lot more information, and a possible solution

We recently modified a large Delphi application to use ADO connection

3条回答
  •  猫巷女王i
    2020-12-13 22:08

    i found the performance problems with ADOExpress years ago:

    • ADO vs ADOExpress time trials. Not good for ADOExpress (6/7/2005)
    • ADO vs ADO Express Time Trials (redux) (12/30/2007)

    Note: Before ADO became a standard part of Delphi, Borland was selling it as an addon called ADOExpress. It was simply object wrappers around Microsoft's ActiveX Data Objects (ADO) COM objects.

    i had tested three scenarios

    • using ADO directly (i.e. Microsoft's COM objects directly)
    • using ADOExpress (Borland's object wrappers around ADO)
    • specifying .DisableControls on the TADOQuery before calling Open

    i discovered

    • use Query.DisableControls to make each call .Next 50x faster
    • use Query.Recordset.Fields.Items['columnName'].Value rather than Query.FieldByName('columnName') to make each value lookup 2.7x faster
    • using TADODataSet (verses TADOQuery) makes no difference

                                      Loop Results        Get Values 
      ADOExpress:                         28.0s              46.6s 
      ADOExpress w/DisableControls:        0.5s              17.0s 
      ADO (direct use of interfaces):      0.2s               4.7s 
      

    Note: These values are for looping 20,881 rows, and looking up the values of 21 columns.

    Baseline Bad Code:

    var
       qry: TADOQuery;
    begin
       qry := TADOQuery.Create(nil);
       try
          qry.SQL.Add(CommandText);
          qry.Open;
          while not qry.EOF do
          begin
             ...
             qry.Next;
          end;
    

    Use DisableControls to make looping 5000% faster:

    var
       qry: TADOQuery;
    begin
       qry := TADOQuery.Create(nil);
       try 
          qry.DisableControls;
          qry.SQL.Add(CommandText);
          qry.Open;
          while not qry.EOF do
          begin
             ...
             qry.Next;
          end;
    

    Use Fields collection to make value lookups 270% faster:

    var
       qry: TADOQuery;
    begin
       qry := TADOQuery.Create(nil);
       try 
          qry.DisableControls;
          qry.SQL.Add(CommandText);
          qry.Open;
          while not qry.EOF do
          begin
             value1 := VarAsString(qry.Recordset.Fields['FieldOne'].Value);
             value2 := VarAsInt(qry.Recordset.Fields['FieldTwo'].Value);
             value3 := VarAsInt64(qry.Recordset.Fields['FieldTwo'].Value);
             value4 := VarAsFloat(qry.Recordset.Fields['FieldThree'].Value);
             value5 := VarAsWideString(qry.Recordset.Fields['FieldFour'].Value);
             ...
             value56 := VarAsMoney(qry.Recordset.Fields['FieldFive'].Value);
             qry.Next;
          end;
    

    Since it is a common enough problem, we created a helper method to solve the issue:

    class function TADOHelper.Execute(const Connection: TADOConnection; 
           const CommandText: WideString): TADOQuery;
    var
       rs: _Recordset;
       query: TADOQuery;
       nRecords: OleVariant;
    begin
       Query := TADOQuery.Create(nil);
       Query.DisableControls; //speeds up Query.Next by a magnitude
       Query.Connection := Connection;
       Query.SQL.Text := CommandText;
       try
          Query.Open();
       except
          on E:Exception do
          begin
             Query.Free;
             raise;
          end;
       end;
       Result := Query;
    end;
    

提交回复
热议问题