gpt4 book ai didi

Delphi ClientDataSet - 删除操作 - 为什么这么慢?

转载 作者:行者123 更新时间:2023-12-02 10:12:21 29 4
gpt4 key购买 nike

我在应用程序中使用 TClientDataSet 来管理从多个 CSV 文件导入的数据负载。总共可以是一百万个或更多条目。我希望能够删除与特定 CSV 文件关联的所有数据集条目,但删除大量项目的时间非常慢。

作为尝试确定我是否做了一些愚蠢的事情的测试,我创建了一个简单的控制台应用程序。它所做的只是:

  • 创建一个 TClientDataSet 实例,并定义 1 个字段 (ID):

    CDS := TClientDataSet.Create(nil);
    CDS.FieldDefs.Add('ID', ftInteger);
    CDS.CreateDataSet;
    CDS.LogChanges := False;

  • 附加 100,000 个项目(需要 0.1 秒):

    for i := 1 to 100000 do
    begin
    CDS.AppendRecord([i]);
    end;

  • 删除 50,000 个项目(大约需要 4 秒,或者使用 LogChanges=TRUE 大约需要 4.4 秒):

    CDS.First;
    while CDS['ID'] <= 50000 do
    CDS.Delete;

如果我的数据集中有 150 万个项目,并且想要删除 050 万个项目,那么通过这种方法删除项目需要很长时间,以至于我什至无法测量它。

作为目前的解决方法,我必须创建一个新数据集,然后将我想要保留的所有项目复制到新副本并删除原始副本。除非我只从原始数据集中删除一小部分条目,否则此方法要快得多。

也许我没有使用最合适的方法来尝试从数据集中删除项目?我猜它会触发我删除的每个项目的一系列内部处理。有没有什么方法可以一次性删除我丢失的一系列项目?也许我可以设置一个索引和基于该索引的范围,然后通过一次操作删除当前范围内的所有项目?

也许问题出在 ClientDataSet 而不是我?也许我需要使用不同的组件。有什么建议吗?

最佳答案

我想我不妨提供我自己的(临时/也许永久?)解决方法的详细信息,以防遇到相同问题的人感兴趣。

问题:与添加项目的初始时间(40 或更多)相比,使用删除操作时,从大型 TClientDataSet(100k 或更多记录)中删除大部分记录需要很长时间。

解决方案:将您不想删除的所有记录复制到新数据集,然后删除原始数据集。 [缺点:更改日志丢失,需要额外的 RAM?]

var
CDS: TClientDataSet;

// initialize new CDS instance
function CreateNewCDSInstance: TCLientDataSet;
begin
Result := TClientDataSet.Create(nil);
Result.FieldDefs.Add('ID', ftInteger);
Result.CreateDataSet;
Result.LogChanges := False;
end;

// close + free CDS instance
procedure CloseCDS;
begin
CDS.EmptyDataSet;
CDS.Close;
CDS.Free;
end;

// delete current record?
function CanDeleteCurrentRecord: boolean;
begin
Result := CDS['ID'] < 50001; //in this simple example
// in my application it would be more like:
// "CDS['FILE_ID'] = AFileIDToDelete"
end;

// delete block of records:
procedure DeleteRecords;
var
aNewCopy: TClientDataSet;
begin
aNewCopy := CreateNewCDSInstance;
CDS.First;
while not CDS.EoF do
begin
if not CanDeleteCurrentRecord then
begin
// NB: AppendRecord takes array of values corresponding to field defintions
aNewCopy.AppendRecord([CDS['ID']]);
end;
CDS.Next;
end;
CloseCDS;
CDS := aNewCopy;
//NB: If you have any aggregates/indexes defined, they must be redefined
end;

使用上面给出的示例,这种删除 50k 项的方法需要 94 毫秒,而不是大约 4 秒。

然而,在提出这个问题并阅读评论时,我发现这个解决方案更像是绷带而不是治疗方法。更大的问题是我正在开发的系统并没有很好地设计来处理它所需的数据量。也许与其说是“TClientDataSet 的问题”,不如说是“我们如何使用 TClientDataSet 的问题”!即使修复了删除速度,导入越来越大的文件和数量的文件以及管理该数据仍然会出现性能问题。

也许(在下雨天!)我将开始研究一种类似于 SilverWarior 建议的方法,即使用单独的数据集来保存每个导入的文件,而不是将所有数据挥霍到一个巨大的内存表中。然后删除文件就相当于删除数据集 - 还有其他潜在的好处。

关于Delphi ClientDataSet - 删除操作 - 为什么这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38945450/

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