web-dev-qa-db-ja.com

Postgres:count(*)とcount(id)

私は documentationcount(*)count(pk)の違いを見ました。私はcount(pk)の存在を知らないcount(*)pkは_SERIAL PRIMARY KEY_です)を使用していました。

私の質問はPostgresの内部最適化についてです。 _SERIAL PRIMARY KEY_がすべての行に存在し、偽になることはなく、単に行をカウントすること、または各行の冗長な述語チェックを行うことをピックアップするのに十分スマートですか?これはおそらく無意味な最適化では多すぎると私は同意しますが、私は興味があるだけです。

EXPLAINと_EXPLAIN VERBOSE_のcount(*)count(id)count(id > 50)の出力を見て、EXPLAINは、その出力で述語をチェックすることについて言及しました。そうではありません。

11
ldrg

過去数年間、さまざまなバージョンで繰り返しテストを行った結果、一貫した結果が得られました。
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(*)に変換されます。

15