0

我最近根据我的经验回答了这个问题:

在进行实际搜索之前计算行数

但我对我给出的答案并不是 100% 满意。

COUNT问题基本上是这样的:在决定运行带回实际行的查询之前,我可以通过运行特定查询来提高性能吗?

我的直觉是:您只会节省与检索数据相关的 I/O 和连线时间,而不是计数,因为要计算数据,您需要实际找到行。可能的例外是查询是索引的简单函数。

那么我的问题是:这总是正确的吗?还有哪些例外情况?从纯粹的性能角度来看,在什么情况下需要COUNT在运行完整查询之前执行?

4

1 回答 1

1

首先,您的问题的答案高度依赖于数据库。

我想不出在查询之前执行 COUNT() 会缩短查询和 count() 的总时间的情况。

通常,进行计数会将表和索引预加载到页面缓存中。假设数据适合内存,这将使后续查询运行得更快(尽管如果您有快速 I/O 并且数据库执行预读页面读取,则速度不会快很多)。但是,您只是将时间范围转移到 COUNT(),而不是减少总时间。

要缩短总时间(包括 COUNT() 的运行时间)需要更改执行计划。以下是理论上可能发生的两种方式:

  1. 数据库可以在读入表时更新统计信息,而这些统计信息又会更改主查询的查询计划。
  2. 数据库可以根据表/索引是否已经在页面缓存中来更改执行计划。

虽然理论上是可能的,但我不知道有任何数据库可以做到这些。

您可以想象可以存储中间结果,但这会违反 SQL 数据库的动态特性。也就是说,更新/插入可能发生在 COUNT() 和查询之间的表上。数据库引擎无法保持完整性并保持这样的中间结果。

相对于加快后续查询,执行 COUNT() 有缺点。COUNT() 的查询计划可能与主查询的查询计划完全不同。您的索引示例就是一种情况。另一种情况是在列式数据库中,不需要读取数据的不同垂直分区。

还有一种情况是查询,例如:

select t.*, r.val
from table t left outer join
     ref r
     on t.refID = r.refID

refID 是 ref 表上的唯一索引。由于没有重复,并且使用了 t 中的所有记录,因此可以消除此连接。但是,此查询显然需要连接。再一次,SQL 优化器是否识别并处理这种情况完全取决于数据库的编写者。但是,理论上可以针对 COUNT() 优化连接。

于 2012-07-25T18:01:20.520 回答