我如何能够非常快速地将数百万条记录从tadotable加载到字符串列表中?
procedure TForm1.SlowLoadingIntoStringList(StringList: TStringList);
begin
StringList.Clear;
with SourceTable do
begin
Open;
DisableControls;
try
while not EOF do
begin
StringList.Add(FieldByName('OriginalData').AsString);
Next;
end;
finally
EnableControls;
Close;
end;
end;
答案 0 :(得分:10)
procedure TForm1.SlowLoadingIntoStringList(StringList: TStringList);
var
oField: TField;
begin
StringList.Clear;
with SourceTable do
begin
Open;
DisableControls;
try
oField:= FieldByName('OriginalData');
if oField<>Nil then
begin
while not EOF do
begin
StringList.Add(oField.AsString);
Next;
end;
end;
finally
EnableControls;
Close;
end;
end;
end;
答案 1 :(得分:4)
不幸的是,你不能快速做到这一点。这是一个固有的慢速操作,需要大量的CPU时间和内存带宽才能实现。你可以投入更多的硬件,但我怀疑你应该重新考虑你的任务。
答案 2 :(得分:1)
有'数百万条记录',您可以考虑: 1 /更改您的查询
SELECT * FROM MYTABLE;
in
SELECT OriginalData FROM MYTABLE;
您将使用更少的内存并提高效率。
2 /根据您的需要,查看除TStringList之外的其他组件。
3 /看看以前所有好的建议,主要是:
答案 3 :(得分:0)
是否排序?
// Turn off the sort for now
StringList.Sorted := False;
// Preallocate the space
StringList.Capacity := recordCount;
// Now add the data with Append()
...
// Now turn the sort back on
StringList.Sorted := True;
答案 4 :(得分:0)
真的?字符串列表中的数百万条记录?
好的,我们假设您确实需要采用这种方法......
已经发布了一些好的建议。
如果你想尝试不同的方法,可以考虑连接单个记录服务器端(通过存储过程),然后将连接数据作为blob(或可能是nvarchar(max))返回,这基本上就是列表由回车符分隔的连接字符串(假设这是符合您需要的合理分隔符)。
然后,您可以简单地将返回的值分配给TStringList的Text属性。
即使您不能在一次点击中完成所有字符串,您也可以一次以1000个为一组进行操作。
这样可以节省大量时间在每个记录客户端循环。
答案 5 :(得分:0)
扩展@ Ravaut123的答案我会建议以下代码:
确保您的查询没有连接到任何可视的其他组件,并且没有任何事件设置在行更改上触发,因为这将导致它更新活动记录中的每个更改,从而减慢速度。 />
您可以使用disablecontrols
禁用可视控件,但不能禁用事件和非可视控件。
...
SQLatable:= 'SELECT SingleField FROM atable ORDER BY indexedfield ASC';
AQuery:= TAdoQuery.Create(Form1);
AQuery.Connection:= ....
AQuery.SQL.Text:= SQLatable;
使用查询确保您只按所需顺序选择1个字段,这样可以减少网络流量。表获取所有字段,导致更多开销。
function TForm1.LoadingAllIntoStringList(AQuery: TAdoQuery): TStringList;
var
Field1: TField;
begin
Result:= nil;
try
if not(AQuery.Active) then begin
AQuery.Open;
end else begin
AQuery.First;
end;
AQuery.DisableControls;
AQuery.Filtered:= false; //Filter in the SQL `where` clause
AQuery.FetchAll; //Preload all data into memory
Result:= TStringlist.Create;
except
{ignore error, will return nil}
end;
try
Result.Sorted:= false; //Make sure you don't enable sorting
Result.Capacity:= AQuery.RecordCount; //Preallocate the needed space
Field1:= AQuery.FieldByName('SingleField'); //Never use `fieldbyname` in a loop!
while not AQuery.EOF do begin
Result.Add(Field1.AsString);
AQuery.Next;
end; {while}
AQuery.EnableControls;
except
FreeAndNil(Result);
end;
如果要将数据加载到字符串列表中以进行某些处理,请考虑在SQL语句中执行此操作。 DB可以使用stringlist不能使用的索引和其他优化
如果要将该数据保存到CSV文件中,请考虑使用内置数据库功能。
例如MySQL有:
SELECT X FROM table1 INTO OUTFILE 'c:/filename_of_csv_file.txt'
将为您创建CSV文件。
许多DB都具有类似的功能。