私は documentation でcount(*)
とcount(pk)
の違いを見ました。私はcount(pk)
の存在を知らないcount(*)
(pk
は_SERIAL PRIMARY KEY
_です)を使用していました。
私の質問はPostgresの内部最適化についてです。 _SERIAL PRIMARY KEY
_がすべての行に存在し、偽になることはなく、単に行をカウントすること、または各行の冗長な述語チェックを行うことをピックアップするのに十分スマートですか?これはおそらく無意味な最適化では多すぎると私は同意しますが、私は興味があるだけです。
EXPLAIN
と_EXPLAIN VERBOSE
_のcount(*)
、count(id)
とcount(id > 50)
の出力を見て、EXPLAIN
は、その出力で述語をチェックすることについて言及しました。そうではありません。
過去数年間、さまざまなバージョンで繰り返しテストを行った結果、一貫した結果が得られました。count(*)
はcount(pk)
よりも少し高速です。また、これは短く、ほとんどの場合、テストされたもの、つまり行の存在によりよく適合します。
について:
Postgresは、_
SERIAL PRIMARY KEY
_がすべての行に存在し、決してfalseになることを拾うのに十分賢いですか?
関連する唯一のものは_NOT NULL
_制約です。 _PRIMARY KEY
_は自動的に_NOT NULL
_であり、serial
または_never false
_は質問と直交しています。
count(col)
を使用すると、ifPostgreSQLはスマートになり、システムカタログで列が_NOT NULL
_であり、同等のcount(*)
に戻ると、count(*)
を使用した場合よりも、システムテーブルのルックアップが1つ多くなります。
EXPLAIN
出力に関しては、ヒントisがあります:
_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)
はnotが_NOT NULL
_で定義されている場合でもcount(*)
に変換されます。