PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Szybki sposób na sprawdzenie liczby wierszy tabeli w PostgreSQL

Wiadomo, że w PostgreSQL zliczanie wierszy w dużych tabelach jest powolne. Model MVCC wymaga pełnej liczby aktywnych wierszy w celu uzyskania dokładnej liczby. Istnieją obejścia, które mogą znacznie przyspieszyć to jeśli liczba nie muszą być dokładne tak jak wydaje się być w twoim przypadku.

(Pamiętaj, że nawet „dokładna” liczba jest potencjalnie martwa w momencie przybycia!)

Dokładna liczba

Powoli dla dużych tabel.
W przypadku współbieżnych operacji zapisu może być nieaktualny w momencie, gdy go otrzymasz.

SELECT count(*) AS exact_count FROM myschema.mytable;
Oszacowanie

Niezwykle szybki :

SELECT reltuples AS estimate FROM pg_class where relname = 'mytable';

Zazwyczaj oszacowanie jest bardzo zbliżone. Jak blisko, zależy od tego, czy ANALYZE lub VACUUM są wystarczająco uruchomione - gdzie "wystarczająco" jest określone przez poziom aktywności zapisu do twojego stołu.

Bezpieczniejsze oszacowanie

Powyższe pomija możliwość istnienia wielu 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';

Rzut na bigint formatuje real liczba ładnie, szczególnie dla dużych liczb.

Lepsze oszacowanie

SELECT reltuples::bigint AS estimate
FROM   pg_class
WHERE  oid = 'myschema.mytable'::regclass;

Szybciej, prościej, bezpieczniej, bardziej elegancko. Zobacz podręcznik na temat typów identyfikatorów obiektów.

Zastąp 'myschema.mytable'::regclass z to_regclass('myschema.mytable') w Postgresie 9.4+, aby otrzymać nic zamiast wyjątku dla nieprawidłowych nazw tabel. Zobacz:

  • Jak sprawdzić, czy tabela istnieje w danym schemacie

Jeszcze lepsze oszacowanie (przy bardzo niewielkim dodatkowym koszcie)

Możemy zrobić to, co robi planista Postgres. Cytując przykłady szacowania wierszy w instrukcji:

Te liczby są aktualne na dzień ostatniego VACUUM lub ANALYZE na stole. Następnie planista pobiera aktualną liczbę stron z tabeli (jest to tania operacja, niewymagająca skanowania tabeli). Jeśli to różni się od relpages następnie reltuples jest odpowiednio skalowany, aby uzyskać aktualną szacunkową liczbę wierszy.

Postgres używa estimate_rel_size zdefiniowane w src/backend/utils/adt/plancat.c , który obejmuje również narożny przypadek braku danych w pg_class ponieważ relacja nigdy nie została odkurzona. Możemy zrobić coś podobnego w SQL:

Minimalna forma

SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
FROM   pg_class
WHERE  oid = 'mytable'::regclass;  -- your table here

Bezpieczne i jednoznaczne

SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
             WHEN c.relpages = 0 THEN float8 '0'  -- empty table
             ELSE c.reltuples / c.relpages END
      * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
       )::bigint
FROM   pg_class c
WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here

Nie łamie się z pustymi tabelami i tabelami, które nigdy nie widziały VACUUM lub ANALYZE . Podręcznik na pg_class :

Jeśli tabela nigdy nie została jeszcze odkurzona ani przeanalizowana, reltuples zawiera -1 wskazując, że liczba wierszy jest nieznana.

Jeśli to zapytanie zwraca NULL , uruchom ANALYZE lub VACUUM do stołu i powtórz. (Alternatywnie możesz oszacować szerokość wiersza na podstawie typów kolumn, takich jak Postgres, ale jest to żmudne i podatne na błędy.)

Jeśli to zapytanie zwraca 0 , tabela wydaje się być pusta. Ale ja bym ANALYZE upewniać się. (A może sprawdź swój autovacuum ustawienia.)

Zazwyczaj block_size wynosi 8192. current_setting('block_size')::int obejmuje rzadkie wyjątki.

Kwalifikacje tabeli i schematu sprawiają, że jest on odporny na każdą search_path i zakres.

Tak czy inaczej, zapytanie konsekwentnie zajmuje mi <0,1 ms.

Więcej zasobów internetowych:

  • Najczęściej zadawane pytania dotyczące Postgres Wiki
  • Strony wiki Postgresa dla szacowanej liczby i wydajności count(*)

TABLESAMPLE SYSTEM (n) w Postgresie 9.5+

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

Jak skomentował @a_horse, dodana klauzula dla SELECT polecenie może być przydatne, jeśli statystyki w pg_class z jakiegoś powodu nie są wystarczająco aktualne. Na przykład:

  • Brak autovacuum bieganie.
  • Zaraz po dużym INSERT / UPDATE / DELETE .
  • TEMPORARY tabele (które nie są objęte autovacuum ).

To dotyczy tylko losowych n % (1 w przykładzie) wybór bloków i zliczanie w nim wierszy. Większa próbka zwiększa koszty i zmniejsza błąd, Twój wybór. Dokładność zależy od większej liczby czynników:

  • Rozkład wielkości wiersza. Jeśli dany blok zawiera szersze niż zwykle wiersze, liczba jest mniejsza niż zwykle itp.
  • Martwe krotki lub FILLFACTOR zajmują miejsce na blok. W przypadku nierównomiernego rozmieszczenia w tabeli oszacowanie może być nieprawidłowe.
  • Ogólne błędy zaokrąglania.

Zazwyczaj oszacowanie z pg_class będzie szybszy i dokładniejszy.

Odpowiedź na aktualne pytanie

Najpierw muszę znać liczbę wierszy w tej tabeli, jeśli suma jest większa niż jakaś predefiniowana stała,

I czy to...

... jest możliwe w momencie, gdy licznik przekroczy moją stałą wartość, zatrzyma liczenie (i nie będzie czekał na zakończenie liczenia, aby poinformować, że liczba wierszy jest większa).

Tak. Możesz użyć podzapytania z LIMIT :

SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

Postgres właściwie przestaje liczyć poza podany limit otrzymujesz dokładny i aktualny licz na maksymalnie n wiersze (500000 w przykładzie) i n Inaczej. Nie tak szybko, jak oszacowanie w pg_class jednak.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak sprawdzić wersję PostgreSQL

  2. Jak zwiększyć maksymalną liczbę połączeń w postgresie?

  3. PHP nie ładuje php_pgsql.dll w systemie Windows

  4. pg_ctl Wskazówki i porady

  5. PostgreSQL UTWÓRZ TABELĘ