gpt4 book ai didi

sql-server - ADOQuery.Locate 慢,创建索引

转载 作者:行者123 更新时间:2023-12-05 03:54:09 29 4
gpt4 key购买 nike

我有以下行来定位查询中的一行。

if Query.Locate('Line;Hour;Minute',VarArrayOf([Line-400,AHour,minuteof(Start)]),[]) = true then

这很慢,现在我记得可以将索引添加到查询中,这样定位本身就会快好几倍。不幸的是,我似乎找不到这个例子。

有人可以帮帮我吗?问候罗伯特

最佳答案

有趣的问题。

更新请参阅下面的更新。

我在 SS2014 Sql Server 上设置了一些测试数据,以使用如下代码运行一些测试:

ID := 1;
for Line := 1 to 1000 do begin
for AHour := 1 to 24 do begin
for AMinute := 1 to 60 do begin
AdoQuery1.InsertRecord([ID, Line, AHour, AMinute]);
Inc(ID);
end;
end;
end;
end;

然后,我运行了一些像这样的测试

procedure TForm1.LocateTest1(DisableControls, UseSort : Boolean);
var
T1 : Integer;
Line,
AHour,
AMinute : Integer;
begin

AdoQuery1.Sql.Text := 'select * from linetest order by line, ahour, aminute';
AdoQuery1.CursorLocation := clUseClient;
AdoQuery1.Open;
T1 := GettickCount;
if DisableControls then
AdoQuery1.DisableControls;

if UseSort then
AdoQuery1.Recordset.Sort := 'Line,AHour,AMinute';
Line := 1000;
AHour := 23;
for AMinute := 60 downto 1 do begin
if not AdoQuery1.Locate('Line;AHour;AMinute', VarArrayOf([Line, AHour, AMinute]), []) then
Caption := Format('Locate failed %d %d %d', [Line, AHour, AMinute]);
end;
Memo1.Lines.Add('Test1 : ' + IntToStr(GetTickCount - T1));
if DisableControls then
AdoQuery1.EnableControls;
AdoQuery1.Close;
end;

之所以涉及Disable/EnableControls是因为我报的结果这里Why does scrolling through ADOTable get slower and slower?,即使没有 db-aware,调用 DisableControls 也会对滚动速度产生巨大影响涉及控制。

但是,滚动似乎不会对在 TAdoQuery 上执行 Locate() 产生重大影响,因为调用 DisableControls 只花费了大约 1.5 秒的记录时间26 秒。显然,TAdoQuery.Locate 在处理大量行时表现不佳。

UseSort 参数的想法是看是否对后面的 RecordSet 进行排序AdoQuery 对速度有任何影响,但没有,原因是 Locate 调用TCustomAdoDataSet.LocateRecord 无论如何都使用 Sort。

您提到了添加索引。不幸的是,TAdoQuery 只支持使用服务器端索引在执行 thq SQL 查询时,未在检索的结果集中定位记录。您可以添加客户端索引到 TAdoTable,但根据与上述类似的测试,令我惊讶的是,他们做了Locate() 的速度几乎没有差异。

因此,鉴于我目前的结果,使用参数化的方法似乎可能更快SELECT 仅检索当前感兴趣的行,而不是尝试定位它在一个大的测试集中。或者,您可以通过 DatasetProvider 或 FireDAC FDMemTable 等将结果集检索到 ClientDataSer 中。Ymmv,这取决于您正在做什么...

更新 自发布我的原始答案以来,我有一些进一步的更新包括在内可能会有用。

  • 其中一个涉及使用调用 AdoQuery 的 RecordSet 的 Find 和 Filter 方法来模仿 Locate 的方法,这种方法比重复执行 AdoQuery1.Locate 快得多(大约 15 秒)。我仍在解决这个问题,将在一两天内发布另一个更新。

  • 另一个是简要提及执行定位时执行 FireDAC FDQuery 而不是 AdoQuery。这似乎在 9 秒内完成了与使用 AdoQuery 大约需要 25 秒的同一组定位,使用以下代码:

使用 FDQuery.Locate

procedure TForm2.LocateTest;
var
T1 : Integer;
Line,
AHour,
AMinute : Integer;
begin

FDQuery1.Sql.Text := 'select * from linetest order by line, ahour desc, aminute desc';
//FDQuery1.CursorLocation := clUseClient;
FDQuery1.CursorKind := ckForwardOnly;
FDQuery1.Open;

T1 := GettickCount;
Line := 1000;
AHour := 1;

for AMinute := 1 to 60 do begin
if not FDQuery1.Locate('Line;AHour;AMinute', VarArrayOf([Line, AHour, AMinute]), []) then
Caption := Format('Locate failed %d %d %d', [Line, AHour, AMinute]);
end;

Memo1.Lines.Add('Test1 : ' + IntToStr(GetTickCount - T1));
FDQuery1.Close;
end;

关于sql-server - ADOQuery.Locate 慢,创建索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61246225/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com