加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

表现 – BDE与ADO在德尔福

发布时间:2020-12-15 06:09:44 所属栏目:大数据 来源:网络整理
导读:请注意下面的编辑更多信息,以及可能的解决方案 我们最近修改了一个大型Delphi应用程序来使用ADO连接和查询而不是BDE连接和查询.由于这种变化,表现已经变得可怕了. 我已经分析了应用程序,并且瓶颈似乎在实际调用TADOQuery.Open.换句话说,从代码角度来看,除了
请注意下面的编辑更多信息,以及可能的解决方案

我们最近修改了一个大型Delphi应用程序来使用ADO连接和查询而不是BDE连接和查询.由于这种变化,表现已经变得可怕了.

我已经分析了应用程序,并且瓶颈似乎在实际调用TADOQuery.Open.换句话说,从代码角度来看,除了重组应用程序以减少实际使用的数据之外,还没有太多的工作来改进这一点.

有没有人有关于如何提高ADO连接的Delphi应用程序的性能的建议?我已经尝试了suggestions given here,几乎没有任何影响.

为了给出性能差异的想法,我对同样大的操作进行了基准测试:

>在BDE下:11秒
>在ADO下:73秒
>在该文章引用的更改后的ADO下:72秒

我们正在客户端 – 服务器环境中使用Oracle后端.本地计算机每个维护与数据库的单独连接.

为了记录,连接字符串如下所示:

const
  c_ADOConnString = 'Provider=OraOLEDB.Oracle.1;Persist Security Info=True;' +
                    'Extended Properties="plsqlrset=1";' +
                    'Data Source=DATABASE.DOMAIN.COM;OPTION=35;' +
                    'User ID=******;Password=*******';

回答zendar提出的问题:

我在Windows Vista和XP上使用Delphi 2007.

后端是Oracle 10g数据库.

如连接字符串所示,我们使用OraOLEDB驱动程序.

我的基准机器上的MDAC版本是6.0.

编辑:

在BDE下,我们有很多代码看起来像这样:

procedure MyBDEProc;
var
  qry: TQuery;
begin
  //fast under BDE,but slow under ADO!!
  qry := TQuery.Create(Self);
  try
    with qry do begin
      Database := g_Database;
      Sql.Clear;
      Sql.Add('SELECT');
      Sql.Add('  FIELD1');
      Sql.Add(',FIELD2');
      Sql.Add(',FIELD3');
      Sql.Add('FROM');
      Sql.Add('  TABLE1');
      Sql.Add('WHERE SOME_FIELD = SOME_CONDITION');
      Open;
      //do something
      Close;
    end;  //with
  finally
    FreeAndNil(qry);
  end;  //try-finally
end;  //proc

但是我们发现在ADO下调用Sql.Add实际上是非常昂贵的,因为每次更改CommandText时都会触发QueryChanged事件.所以用这个代替以上更快:

procedure MyADOProc;
var
  qry: TADOQuery;
begin
  //fast(er) under ADO
  qry := TADOQuery.Create(Self);
  try
    with qry do begin
      Connection := g_Connection;
      Sql.Text := ' SELECT ';
        + '   FIELD1 '
        + ',FIELD2 '
        + ',FIELD3 '
        + ' FROM '
        + '  TABLE1 '
        + ' WHERE SOME_FIELD = SOME_CONDITION ';
      Open;
      //do something
      Close;
    end;  //with
  finally
    FreeAndNil(qry);
  end;  //try-finally
end;  //proc

更好的是,您可以从ADODB.pas中复制TADOQuery,将其重命名为新名称,然后将QueryChanged事件(根据我所知道的)完全没有任何用处.然后使用您的新版本的TADOQuery,而不是本机版本.

type
  TADOQueryTurbo = class(TCustomADODataSet)
  private
    //
  protected
    procedure QueryChanged(Sender: TObject);
  public
    FSQL: TWideStrings;
    FRowsAffected: Integer;
    function GetSQL: TWideStrings;
    procedure SetSQL(const Value: TWideStrings);
    procedure Open;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function ExecSQL: Integer; {for TQuery compatibility}
    property RowsAffected: Integer read FRowsAffected;
  published
    property CommandTimeout;
    property DataSource;
    property EnableBCD;
    property ParamCheck;
    property Parameters;
    property Prepared;
    property SQL: TWideStrings read FSQL write SetSQL;
  end;
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
constructor TADOQueryTurbo.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FSQL := TWideStringList.Create;
  TWideStringList(FSQL).OnChange := QueryChanged;
  Command.CommandText := 'SQL'; { Do not localize }
end;

destructor TADOQueryTurbo.Destroy;
begin
  inherited;
 inherited Destroy;
  FreeAndNil(FSQL);
end;

function TADOQueryTurbo.ExecSQL: Integer;
begin
  CommandText := FSQL.Text;
  inherited;
end;

function TADOQueryTurbo.GetSQL: TWideStrings;
begin
  Result := FSQL;
end;

procedure TADOQueryTurbo.Open;
begin
  CommandText := FSQL.Text;
  inherited Open;
end;

procedure TADOQueryTurbo.QueryChanged(Sender: TObject);
begin
// if not (csLoading in ComponentState) then
//    Close;
// CommandText := FSQL.Text;
end;

procedure TADOQueryTurbo.SetSQL(const Value: TWideStrings);
begin
  FSQL.Assign(Value);
  CommandText := FSQL.Text;
end;

解决方法

我不知道Delphi 2007,但是我也用Delphi 7和Oracle 8做了同样的事情.

这是我做的事情

>根据查询设置TAdoDataSet.CursorLocation:

> clUseClient如果查询获取GUI和查询的记录是相对“简单”的 – 没有分组或总和
> clUseServer如果查询有某种聚合(sum,grouping,counting)

>根据查询设置TAdoDataSet.CursorType:

> ctForward仅适用于不需要滚动浏览数据集的报表 – 仅适用于clUseServer
> ctStatic for GUI.这只是使用clUseClient的模式

>根据查询设置TAdoDataSet.LockType:

> ltReadOnly只针对不用于编辑的每个数据集(网格,报告)
>当更改后立即将数据发布到数据库时(例如用户编辑表单上的数据)
>当您更改大量记录时,ltBatchOptimistic.这是为了获取记录数量的情况,然后对它们进行一些处理,然后批量发送更新到数据库.这最好结合clUseClient和ctStatic.

>根据我的经验,Oracle的OLEDB提供商比Oracle OleDb提供者更好.你应该测试一下.编辑:检查Fabricio关于可能的blob问题的评论.>用TAdoDataSet替换TAdoQUery. TAdoQuery是为将应用从BDE转换为ADO而创建的,但是Borland / Codegear的推荐是使用TAdoDataSet>重新检查Oracle连接字符串以确保您没有网络延迟.连接到Oracle需要多长时间? TnsPing多长时间?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读