Postgres: количество (*) против количества (id)


11

Я видел в документации разницу между count(*)а count(pk). Я использовал count(pk)(где pkэто SERIAL PRIMARY KEY), не зная о существовании count(*).

Мой вопрос касается внутренних оптимизаций Postgres. Достаточно ли умен, чтобы понять, что a SERIAL PRIMARY KEYбудет существовать в каждой строке и никогда не быть ложным, и просто считать строки, или он будет выполнять избыточные проверки предикатов для каждой строки? Я согласен, что это, вероятно, слишком бессмысленная оптимизация, но мне просто любопытно.

Я посмотрел на выходные данные EXPLAINи EXPLAIN VERBOSEдля count(*), count(id)и count(id > 50)посмотреть, если EXPLAINупомянуто проверка предикатов в его выводе. Это не так.

Ответы:


15

Я получил стабильные результаты в моих повторных испытаниях с различными версиями в течение последних лет:
count(*)это немного быстрее , чем count(pk). Он также короче, и в большинстве случаев он лучше соответствует тому, что проверено: наличие ряда.

Что касается:

Является ли Postgres достаточно умным, чтобы понять, что a SERIAL PRIMARY KEYсуществует в каждом ряду и никогда не будет ложным

Единственная важная вещь - это NOT NULLограничение. PRIMARY KEYЭто NOT NULLавтоматически, serialили never 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.


Это все еще так с новыми версиями? Я думаю, что на самом деле не нужен поиск для каждого запроса - он может быть кэширован.
Ондра Жижка

1
Кстати, с NOT NULLколонкой, разница велика, если у вас много строк. В нашем случае с миллионами строк, COUNT(*)это в 3 раза быстрее. (Postgres 9.4)
Ондра Жижка
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.