Count(*) czy count(1) oto jest pytanie


Od wielu lat na forach Oraclowych toczy się ideologiczna walka: COUNT(*) czy COUNT(1). Każda z opcji ma swoich zagorzałych przeciwników i zwolenników.
Najczęstszym argumentem grupy popierającej korzystanie z wersji COUNT(1) jest opinia, że COUNT(1) jest szybsze niż COUNT (*). Według tej teorii COUNT (*) do zliczenia wierszy bierze wszystkie kolumny zaś COUNT(1) tylko kolumnę pierwszą, primary key – i dzięki zliczaniu wierszy po indexie zapytanie jest znacznie szybsze.
Brzmiałoby to nawet całkiem sensownie, gdyby tylko to była prawda.... Najwyższy czas obalić te mity.
Ogólna definicja funkcji COUNT wygląda jak poniżej:
COUNT(<expression>)
Funkcja COUNT zlicza wszystkie wystąpienia nie puste (non null) wyrażenia <expressione>.
COUNT(1) jest niczym innym niż COUNT(<EXPRESSION>) gdzie expression = 1 czyli wartością non-null! Funkcja zlicza ilość rekordów w tabeli, dla których wyrażenie <expression> nie jest nulem -> czyli w tym wypadku 1 jest nie nulem dla wszystkich rekordów.
COUNT(*)
zlicza wszystkie rekordy w tabeli.

select count(*),count(manager_id) , count(1), count('dupa' ) from employees;
COUNT(*)
COUNT(MANAGER_ID)
COUNT(1)
COUNT('BANANA')
107
106
107
107
Jeśli chcemy zliczyć ilość rekordów gdzie wyrażenie expression jest non-null (np. ilość rekordów dla których kolumna manager_id jest nie pusta) w tabeli należy skorzystać z funkcji COUNT(manager_id). Jeśli zaś chcemy zliczyć wszystkie rekordy w tabeli powinniśmy użyć dedykowanej go tego konstrukcji funkcji COUNT(*).
Również z punktu widzenia Dobrych Praktyk wersja COUNT(*) jest bardziej stosowna. Gwiazdka jest dość powszechnie stosowanym znakiem  standardowo oznaczającym „wszystko” – COUNT(*) od razu sugeruje zliczenie wszystkich wierszy.
Dla COUNT(1) jak widać po burzliwych dyskusjach na forach – sprawa już nie jest taka oczywista - czy funkcja zlicza tylko pierwszą kolumnę, czy wartości nie puste, czy liczy po indexie? Zdania są podzielone i każda wersja ma swoich zagorzałych zwolenników.
Dla czystości, przejrzystości i jednoznaczności kodu znacznie lepiej używać COUNT(*). Przynajmniej nie ma wątpliwości, jakie zadanie ta funkcja realizuje.
No i na koniec dla wszystkich sceptyków COUNT(*) – argument crème de la crème. Wszyscy czy chcą czy nie chcą i tak ostatecznie używają COUNT(*) - Oracle wewnętrznie przepisuje funkcję COUNT(1) do postaci COUNT(*)…
Dla przeciwników COUNT(*) jest to bardzo niedobra wiadomość, gdyż okazuje się, że i tak wszyscy kończą na COUNT(*).

dowód by Jonathan Lewis

Komentarze