我最近根据自己的经验回答了这个问题:
Counting rows before proceeding to actual searching
但我对我给出的答案并不是100%满意。
问题基本上是这样的:在决定运行带回实际行的查询之前,是否可以通过在特定查询上运行COUNT
来提高性能?
我的直觉是这样的:你只会保存与检索数据而不是计数相关的I / O和连线时间,因为要计算数据,你需要实际找到行。可能的例外是当查询是索引的简单函数时。
我的问题是:这总是如此吗?还有哪些其他例外情况?从纯粹的性能角度来看,在运行完整查询之前,在什么情况下人们想要COUNT
?
答案 0 :(得分:1)
首先,您的问题的答案高度依赖于数据库。
在查询之前执行COUNT()会缩短查询和count()的总时间时,我无法想到这种情况。
通常,执行计数会将表和索引预先加载到页面缓存中。假设数据适合内存,这将使后续查询运行得更快(尽管如果您有快速I / O并且数据库执行预读页面读取速度不是更快)。但是,您刚刚将时间范围转移到COUNT(),而不是缩短总时间。
要缩短总时间(包括COUNT()的运行时间),需要更改执行计划。理论上可以采用以下两种方式:
虽然理论上可行,但我不知道有任何数据库可以执行其中任何一项。
您可以想象可以存储中间结果,但这会违反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()优化连接。