Postgres:count(*)vs count(id)


11

我在文档中看到了count(*)和之间的区别count(pk)。我一直在使用count(pk)(这里pkSERIAL PRIMARY KEY)不知道约的存在count(*)

我的问题是关于Postgres的内部优化。是否足够聪明地知道SERIAL PRIMARY KEY每行中都会存在一个a ,并且永远不会为假,仅对行进行计数?还是会对每行进行多余的谓词检查?我同意这可能是毫无意义的优化,但我很好奇。

我看了看输出EXPLAINEXPLAIN VERBOSEcount(*)count(id)count(id > 50)看看是否EXPLAIN提到检查其输出的断言。没有。

Answers:


15

我在我的各种版本在过去几年反复试验一致的结果:
count(*)快于count(pk)。它也更短,并且在大多数情况下更适合测试:行的存在。

关于:

Postgres是否足够聪明以至于SERIAL PRIMARY KEY会在每一行中都存在a 并且永远不会为假

唯一相关的是NOT NULL约束。的PRIMARY KEYNOT NULL自动,serialnever false正交于问题。

使用count(col)如果 PostgreSQL试图变得聪明,并检查系统目录中是否有某列NOT NULL并回退到等效列count(*),则您在系统表上的查找仍然比使用查找更多count(*)

至于EXPLAIN输出,还有一个暗示:

EXPLAIN SELECT count(*) FROM ...

Aggregate  (cost=4963.38..4963.43 rows=1 width=0) ...


EXPLAIN SELECT count(pk) FROM ...

Aggregate  (cost=4963.38..4963.43 rows=1 width=4) ...

含义,即使已定义,count(col)不会转换为。count(*)NOT NULL


新版本仍然如此吗?我认为它实际上不需要为每个查询都进行查找-可以将其缓存。
OndraŽižka'18

1
顺便说一句,如果您有很多行,则带有一NOT NULL列,差异会很大。在我们具有数百万行的情况下,COUNT(*)速度提高了3倍。(Postgres 9.4)
OndraŽižka18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.