Постгреси: count (*) vs count (id)


11

Я бачив у документації різницю між count(*)і count(pk). Я використовував count(pk)(де pkце SERIAL PRIMARY KEY), не знаючи про існування count(*).

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

Я поглянув на результат EXPLAINі EXPLAIN VERBOSEдля count(*), count(id)і count(id > 50)щоб побачити, чи EXPLAINзгадується перевірка предикатів у його результатах. Це не так.

Відповіді:


15

Я отримав стабільні результати в моїх повторних випробуваннях з різними версіями в протягом останніх років:
count(*)це трохи швидше , ніж count(pk). Він також коротший і більшу частину часу краще відповідає тестуваному: існуванню ряду.

Щодо:

Чи Postgres достатньо розумний, щоб зрозуміти, що 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)
Ondra Žižka
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.