Istnieją trzy sposoby na obliczenie tego rodzaju, każdy z własnymi kompromisami.
Jeśli chcesz prawdziwej liczby, musisz wykonać instrukcję SELECT, taką jak ta, której użyłeś dla każdej tabeli. Wynika to z faktu, że PostgreSQL przechowuje informacje o widoczności wiersza w samym wierszu, a nie gdziekolwiek indziej, więc każda dokładna liczba może dotyczyć tylko niektórych transakcji. Otrzymujesz informację o tym, co widzi ta transakcja w momencie jej wykonania. Możesz to zautomatyzować, aby działało z każdą tabelą w bazie danych, ale prawdopodobnie nie potrzebujesz takiego poziomu dokładności lub nie chcesz czekać tak długo.
Drugie podejście zauważa, że moduł gromadzący statystyki śledzi w przybliżeniu, ile wierszy jest „na żywo” (nie usuwanych ani nieaktualnych przez późniejsze aktualizacje) w dowolnym momencie. Ta wartość może być nieco wyłączona przy dużym obciążeniu, ale ogólnie jest dobrym oszacowaniem:
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
Może to również pokazać liczbę martwych wierszy, co samo w sobie jest interesującą liczbą do monitorowania.
Trzecim sposobem jest zwrócenie uwagi na to, że systemowa komenda ANALYZE, która jest regularnie wykonywana przez proces autovacuum od PostgreSQL 8.3 w celu aktualizacji statystyk tabeli, również oblicza oszacowanie wiersza. Możesz pobrać ten w ten sposób:
SELECT
nspname AS schemaname,relname,reltuples
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE
nspname NOT IN ('pg_catalog', 'information_schema') AND
relkind='r'
ORDER BY reltuples DESC;
Trudno powiedzieć, które z tych zapytań jest lepsze. Zwykle podejmuję tę decyzję na podstawie tego, czy są bardziej przydatne informacje, których chcę również użyć w pg_class, czy w pg_stat_user_tables. Dla podstawowych celów liczenia, aby zobaczyć, jak duże są rzeczy w ogóle, oba powinny być wystarczająco dokładne.
with tbl as (SELECT table_schema,table_name FROM information_schema.tables where table_name not like 'pg_%' and table_schema in ('public')) select table_schema, table_name, (xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, table_name), false, true, '')))[1]::text::int as rows_n from tbl ORDER BY 3 DESC;