SDAC -RecordCount 和 FetchAll

Posted

技术标签:

【中文标题】SDAC -RecordCount 和 FetchAll【英文标题】:SDAC -RecordCount and FetchAll 【发布时间】:2011-09-11 05:02:42 【问题描述】:

我正在使用SDAC 组件来查询 SQL Server 2008 数据库。它有一个recordcountproperty,就像所有数据集一样,它也有FetchAll 属性(我认为它在clientdatasets 上称为packedrecords)。说到这里,我有几个问题:

1 - 如果我设置 FetchAll = True recordcount 属性返回正常。但是在这种情况下,当我有一个大型数据库并且我的查询返回很多行时,有时内存会增长很多(因为它正在获取所有数据以获取 recordcount 当然)。

2 - 如果我设置FetchAll = Falserecordcount 返回 -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 相比会非常慢。有关更多信息,请参阅此问题:***.com/questions/1874888/… 【参考方案1】:

正常运行查询,而不是关闭查询

MSQuery1.SQL.Text := 'select * from cidade';     
MSQuery1.Open;     
MSQuery1.Close;  

您需要close,否则SQL-server 尚未关闭游标,并且不会将查询注册为“已完成”。

然后立即运行以下查询:

SELECT @@rowcount AS num_of_rows

这将选择您上次select 读取的总行数。 它还将选择您的更新/删除/插入语句受影响的行数。

见:http://technet.microsoft.com/en-us/library/ms187316.aspx

请注意,此变量是每个连接,因此其他连接中的查询不会影响您。

【讨论】:

您能否检查一下我的EDIT,看看我是否应该这样做?【参考方案2】:

我使用 ODAC,并且我相信 SDAC 继承自相同的基类并且工作方式与 ODAC 相同。在 ODAC 中,查询组件的选项下有一个名为 QueryRecCount 的选项。在帮助文件中查找 TCustomDADataSet.Options.QueryRecCount。

设置 QueryRecCount = True 和 FetchAll = False 将减少您的内存使用量并为您提供记录数。但 SDAC 将在后台运行第二个查询以获取记录数,因此它确实为您的查询增加了一点额外时间。

查看 http://www.devart.com/forums/viewtopic.php?t=8143 的 Devart 论坛条目。

【讨论】:

是的,它继承自 sabe 基类。但是这个属性并不是一直有效。有些查询不起作用,我只是不知道为什么。此外,如果查询有top 命令,则记录计数会返回错误结果。自己试试吧。 你知道这个属性增加了多少时间(平均)查询执行? 该属性在后台创建一个查询,该查询从 (your query) 执行 select count(*)。我真的不能给你它增加的平均时间,特别是因为我使用的是 ODAC 而不是 SDAC。有时是几毫秒,有时是一两分钟。很多性能取决于您的数据库设计和您正在运行的特定查询。索引、统计数据、数据集大小、数据库服务器设置等都会影响所需时间。不过,我对使用它的结果感到非常满意。 另外,如果您有时会得到不正确的结果(您在使用 top 命令时提到过),请在 Devart 论坛上发布消息或通过电子邮件向他们提供支持。他们非常擅长回答论坛上发布的问题并快速调查错误。

以上是关于SDAC -RecordCount 和 FetchAll的主要内容,如果未能解决你的问题,请参考以下文章

43)PHP,mysql_fetch_row 和mysql_fetch_assoc和mysql_fetch_array

PHP中mysql_fetch_row()mysql_fetch_assoc()和mysql_fetch_array()的联系

学说中 fetch="EAGER" 和 fetch="LAZY" 有啥区别

Fetch 和 Query 有啥区别?

fetch 和 jquery ajax 有啥区别?

Fetch和ajax的比较和区别