0

是的,我知道这个问题类似于这个线程:COUNT(*) vs. COUNT(1) vs. COUNT(pk):哪个更好?,但这有点不同。

我的学长说count(PrimaryKey),假设PrimaryKey不可能NULL,从那里得到结果比做一个正常的要快count(*)。这是真的?

如果这是真的,那么是否适用于所有 RDBMS?如果可能,请参考(半)官方文档。

4

2 回答 2

2

不,这似乎是一个持续存在的误解,基于语法之间的混淆

SELECT * FROM ...

SELECT COUNT(*) FROM ...

在第一种情况下,*引用所有列,返回这些肯定比返回单个列需要更多的资源。在第二种情况下,COUNT(*)它只是“计算所有行数”的简写。错误的信念是,它COUNT(*)以某种方式指示数据库引擎检查所有行中的所有列,而COUNT(<pk_field>)只需要查看一列。

这里还有许多其他关于 SO 的评论引用了 SQL-92 标准,该标准明确指出COUNT(*)应该只引用表的基数,因此,至少在理论上,数据库引擎应该能够识别和优化它。

据我所知,在这两种情况下,大多数数据库引擎(PostgresOracleMySQL InnoDB)只会执行索引扫描来计算行数。如果您指定 PK,则将使用该索引;如果您只使用COUNT(*),则查询计划器将选择一个跨越整个表的索引*,但性能应该相同。

我能找到的唯一例外是带有 MyISAM 表的 MySQL——这些表缓存了行数,所以COUNT(*)速度非常快。但是,查询计划器也将COUNT(<field>), where <field>is any non-null column 识别为对完整表大小的请求,并在这种情况下也使用缓存。(来源)同样,性能没有差异。

*理论上,如果你没有这样的索引,那么COUNT(*)会很慢,但在那种情况下,COUNT(<pk>)根据定义是不可能的

于 2012-09-14T06:06:11.740 回答
0

没关系有几个原因。首先,两种符号——COUNT(1)COUNT(*)——都是错误的语法。考虑关于SUM聚合的相同问题。哦,SUM(*)没有任何意义;为什么?因为,求和是赋值的迭代执行

for( int columnValue : columnList )
   currentSum = currentSum + columnValue;

而对于COUNT聚合它看起来像这样

for( Tuple t : tupleList )
   currentSum = currentSum + 1;

因此,COUNT聚合根本不应该有任何参数!

然后,有各种各样的句法怪癖,比如count distinct。这仅仅证明了 SQL 设计者的无能,他们试图将两个连续的操作(选择不同的元组,然后聚合)压缩到一个操作中。

无关紧要的第二个原因是,在实践中您会遇到无数性能不佳的查询,而COUNT(1)vsCOUNT(*)从来都不是瓶颈。

于 2012-09-13T18:49:16.877 回答