【发布时间】:2023-03-30 15:16:02
【问题描述】:
我正在使用SDAC 组件来查询 SQL Server 2008 数据库。它有一个recordcountproperty,就像所有数据集一样,它也有FetchAll 属性(我认为它在clientdatasets 上称为packedrecords)。说到这里,我有几个问题:
1 - 如果我设置 FetchAll = True recordcount 属性返回正常。但是在这种情况下,当我有一个大型数据库并且我的查询返回很多行时,有时内存会增长很多(因为它正在获取所有数据以获取 recordcount 当然)。
2 - 如果我设置FetchAll = False,recordcount 返回 -1 并且内存不会增长。但我真的需要记录数。而且我还想为此创建一个通用函数,所以我不必更改所有现有的查询。
在这种情况下,我该怎么做才能使recordcount 正常工作并且应用程序的内存使用率较低?
请不要发布我不需要记录计数(或者我应该使用 EOF 和 BOF),因为我确实需要,这不是问题。
我曾考虑使用查询来确定记录计数,但由于我的查询将被执行两次(记录计数为 1,数据为 1),因此存在一些问题
编辑
@Johan 指出了一个很好的解决方案,而且它似乎有效。有人可以证实这一点吗?我为每个 TMSQuery 使用 1 个 TMSCconnection(因为我正在使用线程),所以我认为这不会是一个问题,对吗?
MSQuery1.FetchAll := False;
MSQuery1.FetchRows := 10;
MSQuery1.SQL.Text := 'select * from cidade';
MSQuery1.Open;
ShowMessage(IntToStr(MSQuery1.RecordCount)); //returns 10
MSQuery1.Close;
MSQuery2.SQL.Text := 'SELECT @@rowcount AS num_of_rows';
MSQuery2.Open;
ShowMessage(MSQuery2.FieldByName('num_of_rows').AsString); //returns 289
编辑 2*
MSQuery1 必须关闭,否则MSQuery2 将不会返回num_of_rows。这是为什么呢?
MSQuery1.FetchAll := False;
MSQuery1.FetchRows := 10;
MSQuery1.SQL.Text := 'select * from cidade';
MSQuery1.Open;
ShowMessage(IntToStr(MSQuery1.RecordCount)); //returns 10
//MSQuery1.Close; <<commented
MSQuery2.SQL.Text := 'SELECT @@rowcount AS num_of_rows';
MSQuery2.Open;
ShowMessage(MSQuery2.FieldByName('num_of_rows').AsString); //returns 0
【问题讨论】:
-
你只有三个选择,你已经知道了:1)使用
FetchAll,检索所有行,然后使用RecordCount,2)不要使用FetchAll,因此不要可以访问RecordCount,或3)使用Count()(如果您使用正确的WHERE子句来限制行数,这应该相当快)然后再次执行数据查询。真的没有别的选择了。 -
选择 4 是使用 SQL-server 保留的有关其查询的统计信息,请参阅下面的答案。
-
当连接打开时,您有一个要从中获取的数据库游标,这可以防止@@rowcount 检测到事务已结束。每个线程使用单独的连接是一个好主意,因为这样 sql-server 将为每个连接保留单独的行数,并且不会混淆线程。
-
@Johan,有没有办法在不关闭查询的情况下获得记录数?也许关闭交易或其他东西。关键是,打开查询并获得记录数会很好。
-
您可以使用
select count(*) over ....,但与@@rowcount 相比会非常慢。有关更多信息,请参阅此问题:stackoverflow.com/questions/1874888/…
标签: sql-server delphi dataset memory-management record-count