Zliczanie wierszy w dużych tabelach jest znane w PostgreSQL jako powolne. Aby uzyskać dokładną liczbę, musi wykonać pełne zliczenie wierszy ze względu na charakter MVCC . Istnieje sposób, aby radykalnie to przyspieszyć, jeśli liczba nie musi być dokładna, jak się wydaje w twoim przypadku.
Zamiast uzyskiwać dokładną liczbę ( powolne przy dużych stołach):
SELECT count(*) AS exact_count FROM myschema.mytable;
Otrzymujesz przybliżone oszacowanie w ten sposób ( niezwykle szybko ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
To, jak dokładne jest oszacowanie, zależy od tego, czy biegasz ANALYZE
wystarczająco. Zwykle jest bardzo blisko.
Zobacz FAQ Wiki PostgreSQL .
Lub dedykowana strona wiki dla wydajności count (*) .
Jeszcze lepiej
W artykule w PostgreSQL Wiki jest był nieco niechlujny . Zignorował możliwość, że może istnieć wiele tabel o tej samej nazwie w jednej bazie danych - w różnych schematach. Aby to uwzględnić:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
Albo jeszcze lepiej
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Szybszy, prostszy, bezpieczniejszy, bardziej elegancki. Zobacz podręcznik dotyczący typów identyfikatorów obiektów .
Użyj to_regclass('myschema.mytable')
w Postgres 9.4+, aby uniknąć wyjątków dla nieprawidłowych nazw tabel:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Podobnie jak w komentarzu @a_horse , nowo dodana klauzula SELECT
polecenia może być przydatna, jeśli statystyki w programie pg_class
nie są z jakiegoś powodu wystarczająco aktualne. Na przykład:
- Żadnego
autovacuum
biegania.
- Natychmiast po dużym
INSERT
lub DELETE
.
TEMPORARY
stoły (które nie są objęte autovacuum
).
To patrzy tylko na losowy n % ( 1
w przykładzie) wybór bloków i liczy wiersze w nim. Większa próbka zwiększa koszt i zmniejsza błąd, Twój wybór. Dokładność zależy od wielu czynników:
- Rozkład rozmiaru wiersza. Jeśli zdarzy się, że dany blok ma szersze niż zwykle rzędy, liczba jest mniejsza niż zwykle itp.
- Martwe krotki lub
FILLFACTOR
zajmują miejsce na blok. Jeśli rozkład jest nierównomierny w tabeli, oszacowanie może być nieprawidłowe.
- Ogólne błędy zaokrąglania.
W większości przypadków oszacowanie z pg_class
będzie szybsze i dokładniejsze.
Odpowiedz na aktualne pytanie
Najpierw muszę znać liczbę wierszy w tej tabeli, jeśli całkowita liczba jest większa niż pewna wstępnie zdefiniowana stała,
I czy to ...
... jest możliwe w momencie, gdy licznik przekroczy moją stałą wartość, zatrzyma zliczanie (i nie będzie czekać na zakończenie liczenia, aby poinformować, że liczba wierszy jest większa).
Tak. Możesz użyć podzapytania zLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres faktycznie przestaje liczyć poza podany limit, otrzymasz dokładną i aktualną liczbę dla maksymalnie n wierszy (w przykładzie 500000) i n w przeciwnym razie. pg_class
Jednak nie tak szybko, jak szacowano .