Postgres:计数(*)与计数(id)

ldr*_*drg 12 postgresql optimization count

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

我的问题是关于 Postgres 的内部优化。是否足够聪明地发现 aSERIAL PRIMARY KEY将存在于每一行中并且永远不会为假并且只计算行数,或者它是否会对每一行进行冗余谓词检查?我同意这可能是一个毫无意义的优化,但我只是好奇。

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

Erw*_*ter 15

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

关于:

Postgres 是否足够聪明以发现 aSERIAL PRIMARY KEY将存在于每一行中并且永远不会是假的

唯一相关的是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) ...
Run Code Online (Sandbox Code Playgroud)

这意味着,count(col)转换为count(*),即使它被定义NOT NULL

  • 顺便说一句,如果您有很多行,那么对于“NOT NULL”列,差异是*大*。在我们有数百万行的情况下,`COUNT(*)` 快了 3 倍。(Postgres 9.4) (2认同)