Postgres: liczba (*) a liczba (identyfikator)

11

W dokumentacji widziałem różnicę między count(*)i count(pk). Korzystałem count(pk)(gdzie pka SERIAL PRIMARY KEY) nie wiedząc o istnieniu count(*).

Moje pytanie dotyczy wewnętrznych optymalizacji Postgres. Czy jest wystarczająco mądry, aby stwierdzić, że a SERIAL PRIMARY KEYbędzie istniał w każdym rzędzie i nigdy nie będzie fałszywy i po prostu policzy wiersze, czy też będzie przeprowadzać zbędne sprawdzanie predykatów dla każdego wiersza? Zgadzam się, że jest to chyba zbytnia bezcelowa optymalizacja, ale jestem po prostu ciekawy.

Wziąłem spojrzeć na wyjściu EXPLAINi EXPLAIN VERBOSEna count(*), count(id)i count(id > 50)zobaczyć, czy EXPLAINwspomniane sprawdzania predykatów w swoim wyjściu. Tak nie jest.

ldrg
źródło

Odpowiedzi:

15

W ciągu ostatnich lat otrzymałem spójne wyniki w moich wielokrotnych testach z różnymi wersjami:
count(*)jest nieco szybszy niż count(pk). Jest również krótszy i przez większość czasu lepiej pasuje do tego, co jest testowane: istnienie rzędu.

O:

Czy Postgres jest wystarczająco inteligentny, aby stwierdzić, że a SERIAL PRIMARY KEYbędzie istniał w każdym rzędzie i nigdy nie będzie fałszywy

Jedyną istotną rzeczą jest NOT NULLograniczenie. PRIMARY KEYJest NOT NULLautomatycznie, seriallub never falsesą prostopadłe do pytania.

Dzięki count(col), jeśli PostgreSQL próbowałby być inteligentny i sprawdzić w katalogu systemowym, czy kolumna jest, NOT NULLi powrócić do jej odpowiednika count(*), nadal będziesz mieć jeszcze jedno wyszukiwanie w tabeli systemowej niż za pomocą count(*).

Co do EXPLAINwyjścia, nie jest wskazówką:

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) ...

Znaczenie niecount(col) jest konwertowane na , nawet jeśli jest zdefiniowane .count(*)NOT NULL

Erwin Brandstetter
źródło
Czy nadal tak jest w przypadku nowych wersji? Myślę, że tak naprawdę nie wymagałoby to wyszukiwania dla każdego zapytania - można je było buforować.
Ondra Žižka
1
Przy okazji, z NOT NULLkolumną różnica jest duża, jeśli masz dużo wierszy. W naszym przypadku z milionami rzędów COUNT(*)jest 3 razy szybszy. (Postgres 9.4)
Ondra Žižka