请注意下面的编辑更多信息,以及可能的解决方案
我们最近修改了一个大型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;