我正在尝试配置一个FireDAC TFDQuery组件,以便它按需要以不超过500的批次获取记录,但我需要它报告查询的总记录计数是多少,而不仅仅是获取记录的数量。FetchOptions配置如下:
FetchOptions.AssignedValues = [evMode, evRowsetSize, evRecordCountMode, evCursorKind, evAutoFetchAll]
FetchOptions.CursorKind = ckForwardOnly
FetchOptions.AutoFetchAll = afTruncate
FetchOptions.RecordCountMode = cmTotal
FetchOptions.RowSetSize = 500这将立即返回表中的所有记录,而不仅仅是500。我尝试将RecsMax设置为500,这可以限制获取的记录,但是查询的RecordCount只显示500,而不是总数。
FireDAC帮助文件指出,将RecordCountMode设置为“`cmTotal”将导致FireDAC发出
从(原始SQL命令文本)中选择COUNT(*)。
要么是有错误,要么是我做错了什么!
我看不出我还能改变什么属性。我对RowSetSize和RecsMax之间的关系感到困惑,din也没有发现帮助文件是明确的。
我尝试过使用AutoFetchAll的属性(同样对这个属性的用途感到困惑),但是注意到它被设置为afAll,我将它设置为afTruncate,以查看这是否会产生影响,但它没有。
发布于 2018-08-21 09:06:41
我已经用一个FetchOptions组件和一个FDQuery组件测试了FDTable的fmOnDemand Mode。FetchOptions ie RowSetSize=50的设置都是相同的。通过网络服务器获取数据集中的425,000行。
FDTable按预期执行。它只加载了50个元组,并且几乎是立即加载的。当按Ctrl+End到DBGrid显示的末尾时,它只加载100个元组。虽然滚动它很少加载超过100个元组。对记忆的影响可以忽略不计。但滚动的速度很慢。
FDQuery加载50个元组,但大约需要35秒才能完成,并且在这个过程中消耗了超过0.5GB的内存。如果您按Ctrl+Home移动到连接的DBGrid的末尾,它几乎立即就会这样做,并且在此过程中加载整个表并消耗更多的700 of内存。
我还用CachedUpdates做了实验。以上结果与CachedUpdates关闭。当启动时,对FDQuery的性能没有任何影响(仍然很差),但是对于FDTable,它导致它在启动时加载整个表,花费了半分钟以上的时间,消耗了1.2GB的内存。
看起来,fmOnDemand模式实际上只适用于关闭CachedUpdates的FDTable,根本不适合与FDQuery一起使用。
发布于 2018-08-23 17:46:51
我使用fmOnDemand与postgreSQL和MySQL进行测试的结果基本相同。使用FDTable,fmOnDemand只下载它需要的仅限于RowSetSize的内容。在RowSetSize为50的情况下,它最初下载50个元组,无论滚动到哪里,都不会下载超过111个元组(尽管这无疑取决于连接的DBGrid的大小)。如果您从数据源断开FDTable连接,它最初下载50个元组,然后导航到基础表中的任何记录,它只下载一个元组并丢弃所有其他数据。
FDQuery in fmOnDemand在打开时只下载最初的50个元组,但是如果您通过RecNo导航,它会在中间下载每个元组。我更希望它能使用限制和偏移命令,只获取被请求的记录。
要重新创建PostGre的测试,您需要以下FireDAC组件:
object FDConnectionPG: TFDConnection
Params.Strings = (
'Password='
'Server='
'Port='
'DriverID=PG')
ResourceOptions.AssignedValues = [rvAutoReconnect]
ResourceOptions.AutoReconnect = True
end
object FDQueryPG: TFDQuery
Connection = FDConnectionPG
FetchOptions.AssignedValues = [evMode, evRowsetSize]
end
object FDTable1: TFDTable
CachedUpdates = True
Connection = FDConnectionPG
FetchOptions.AssignedValues = [evMode, evRowsetSize, evRecordCountMode]
FetchOptions.RecordCountMode = cmFetched
end如果希望用MYSQL重新创建它,基本上需要相同的FireDAC组件,但FDConnection需要设置如下:
object FDConnectionMySql: TFDConnection
Params.Strings = (
'DriverID=MySQL'
'ResultMode=Use')
ResourceOptions.AssignedValues = [rvAutoReconnect]
ResourceOptions.AutoReconnect = True
end您需要一个编辑框、两个按钮、一个复选框、一个定时器和一个标签以及以下代码:
procedure TfrmMain.Button1Click(Sender: TObject);
begin
if not FDQueryPG.IsEmpty then
begin
FDQueryPG.EmptyDataSet;
FDQueryPG.ClearDetails;
FDQueryPG.Close;
end;
if not FDTable1.IsEmpty then
begin
FDTAble1.EmptyDataSet;
FDTable1.ClearDetails;
FDTable1.Close;
end;
lFetched.Caption := 'Fetched 0';
lFetched.Update;
if cbTable.checked then
begin
FDTable1.TableName := '[TABLENAME]';
FDTable1.Open();
lFetched.Caption := 'Fetched '+ FDTable1.Table.Rows.Count.ToString;
end
else
begin
FDQueryPG.SQL.Text := 'Select * from [TABLENAME]';
FDQueryPG.open;
lFetched.Caption := 'Fetched '+ FDQueryPG.Table.Rows.Count.ToString;
end;
timer1.Enabled:=true;
end;
procedure TfrmMain.Button2Click(Sender: TObject);
begin
if cbTable.Checked then
FDTable1.RecNo := strToInt(Edit1.Text)
else
FDQueryPG.RecNo := strToInt(Edit1.Text);
end;
procedure TfrmMain.cbTableClick(Sender: TObject);
begin
timer1.Enabled := False;
end;
procedure TfrmMain.Timer1Timer(Sender: TObject);
begin
if cbTable.checked then
lFetched.Caption := 'Fetched '+ FDTable1.Table.Rows.Count.ToString
else
lFetched.Caption:='Fetched '+FDQueryPG.Table.Rows.Count.ToString;
lFetched.Update;
end;https://stackoverflow.com/questions/51895553
复制相似问题