- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我试图支持 this question 时,我被触发问这个问题。具有 MCVE。
我最近开始注意到 TClientDataSet 很快就会耗尽内存。我在生产中遇到了一个问题,它无法加载大约 60.000 个数据集,这对我来说似乎低得惊人。客户端数据集通过提供程序与 ADODataSet 连接,加载良好。我单独运行该查询并将结果输出到 CSV,这给了我一个 < 30MB 的文件。
所以我做了一个小测试,我可以在客户端数据集中加载大约 165K 条记录,其中有一个大小为 4000 的字符串字段。该字段的实际值只有 3 个字符,但这并不'似乎对结果并不重要。
看起来每条记录至少占用这 4000 个字符。 4000 x 2 字节 x 165K 记录 = 1.3GB,因此开始接近 32 位内存限制。如果我把它变成一个备忘录字段,我可以轻松添加 500 万行。
program ClientDataSetTest;
{$APPTYPE CONSOLE}
uses SysUtils, DB, DBClient;
var
c: TClientDataSet;
i: Integer;
begin
c := TClientDataSet.Create(nil);
c.FieldDefs.Add('Id', ftInteger);
c.FieldDefs.Add('Test', ftString, 4000); // Actually claims this much space...
//c.FieldDefs.Add('Test', ftMemo); // Way more space efficient (and not notably slower)
//c.FieldDefs.Add('Test', ftMemo, 1); // But specifying size doesn't have any effect.
c.CreateDataSet;
try
i := 0;
while i < 5000000 do
begin
c.Append;
c['Id'] := i;
c['Test'] := 'xyz';
c.Post;
if (i mod 1000) = 0 then
WriteLn(i, c['Test']);
Inc(i);
end;
except
on e: Exception do
begin
c.Cancel;
WriteLn('Error adding row', i);
Writeln(e.ClassName, ': ', e.Message);
end;
end;
c.SaveToFile('c:\temp\output.xml', dfXML);
Writeln('Press ''any'' key');
ReadLn;
end.
所以问题本身有点广泛,但我希望有一个解决方案,并且能够通过更有效地使用字符串空间来加载更大的数据集。该字段之所以很大,是因为它们可以包含注释。对于大多数记录来说,这些记录都是空的或短的,因此这是对空间的极大浪费。
对于最后一点,我碰巧发现 this question ,隐藏在评论中,提到了 vgLib,但我发现的只是损坏的链接,我什至不知道它是否可以解决这个问题。显然,MidasLib 的 C++ 代码现在已经可用,但由于它是 1.5MB 的晦涩代码,我认为在深入研究之前可能值得在这里询问一下。 ;)
最佳答案
blob 字段(备注)和常规字段存储和检索数据的方式有所不同。 Blob 字段不在记录缓冲区中存储数据(请参阅TBlobField.GetDataSize
),并且在存储或检索该数据时使用一组不同的方法。
每条记录的大小通过调用 TField.GetDataSize
返回。对于 TStringField
,这是所需的字符串大小 + 1。
TCustomClientDataSet.InitBufferPointers
使用此值作为 FRecBufSize
值计算的一部分,该值用作为 TCustomClientDataSet 中的每个记录分配的内存大小。 AllocRecordBuffer
.
那么,回答你的问题:
关于delphi - TClientDataSet 对字符串字段使用了太多内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55375774/
如何从 TClientDataset 获取更改? 我有一个名为 GetDataset 的 TClientDataset 并且有一个网格。我希望在名为 ChangeDataset 的新 TClientD
我有一个包含以下控件的表单:TDBEdit,TDBMemo,TDataSource,TClientDataSet 如果用户编辑字段,然后单击表单上仅调用MyCDS.Cancel方法的按钮(以取消编辑)
我有一个简单的 Delphi (2007) 过程,它给定一个 TDataSet 和一个(子)字段列表返回一个新的 TClientDataSet 和 不同的值 从给定的 TDataSet。 这工作得很好
我们有一个系统可以根据我们的数据创建报告。我们可以处理大量数据。超过 150,000 行的想法并非不可能。 不幸的是,我们对 TClientDataSet 的体验是它的局限性,因为当数据变得太大时,它
我有一个数据库表,我需要在其中插入记录。我正在使用可更新的 TClientDataset,一切正常。 现在,我需要添加一个虚拟字段;不是计算出来的。我可以在其中写入行状态的一个字段(只是我将在 App
我需要过滤TClientDataset,实际上我正在使用这段代码。 if Value<>'' then begin ClientDataSet1.DisableControls;
一些背景:我想开发一个桌面应用程序,使用 SQL 数据库作为存储。一次只有一个用户连接到数据库。 为了使维护更容易,我想将 GUI 与 Busniss Logic 分开。因此,我想到为每个对话框使用一
当我试图支持 this question 时,我被触发问这个问题。具有 MCVE。 我最近开始注意到 TClientDataSet 很快就会耗尽内存。我在生产中遇到了一个问题,它无法加载大约 60.0
我有一个在线程 1 中管理的 TClientDataset。 在另一个线程中,我有一个 TClientDataset 的克隆图像。 我会遇到线程问题吗? 编辑 克隆的图像以只读模式使用。 最佳答案 简
我有一个 DataSnap 服务器,它创建对给定用户 session 唯一的 TSQLQuery、TDataSetProvider 和 TClientDataSet,它们用于和重用从数据库检索数据并将
是否可以将对多个表的多个查询的结果放入 TClientDataset 中? 有点像 SELECT * from t1; SELECT * from t2; SELECT * from t3; 我似乎无
这是我想要完成的: 通过 TSQLDataset 的 CommandText 从数据库中检索 1 条记录:SELECT * FROM myTable WHERE ID = 1 使用TClientDat
我有一个简单的 TClientDataSet 组件,用于填充一些数据感知组件。但是,如果我使用此数据集将数据插入我的数据库,我似乎无法找到将其同步回我的 TClientDataSet 组件的正确方法。
在 TClientDataSet 组件中调用 CreateDataSet 方法时出现“无效参数错误”的原因是什么?导致此错误的原因。 最佳答案 当您有一个 ftString 数据类型字段并且其大小为零
你好代码爱好者! 我有一个问题,这无疑是由于我对 Delphi XE2 知识缺乏经验。我会在这里尝试解释一下。 简介: 我有一个包含数据的 Interbase 数据库。该数据库位于远程机器上。我正在开
我需要在 TClientDataSet 中创建一个聚合字段,但如文档中所述: Choose OK. The newly defined aggregate field is automatically
我使用一个提供程序在主详细信息中有 2 个 ClientDatasets。 2 个基础查询作为主详细信息与数据源连接,并且主查询将详细信息作为字段 (TDatasetField) 我的问题是关闭主(甚
在我的应用程序中,我将 TADOQuery 与 select (MSSQL) 一起使用,并与其 TClientDataSet 链接。我必须插入大约一百万条记录并应用更新。 那么我在 SQL Serve
我想知道是否可以将一个数据集嵌套在一个数据集中,然后将该数据集嵌套在另一个数据集中。因此有 3 层嵌套。目前,我只能将一个数据集嵌套在另一个数据集中。当尝试嵌套第三层时,数据库在我第一次编译程序并且能
我正在使用 TClientDataset 创建一个内存数据集作为接收缓冲区。添加数据很棒,但是一旦我开始处理它,我希望能够从数据集中删除该行。调用删除有效 - 某种程度上 - 行/索引仍然可以访问,但
我是一名优秀的程序员,十分优秀!