DBAtlas · Атлас эксплуатации баз данных

Измерить раздувание таблиц и индексов через pgstattuple

PostgreSQLОбслуживание

Команда

CREATE EXTENSION IF NOT EXISTS pgstattuple;

-- Fast estimate: skips pages marked all-visible in the visibility map
SELECT pg_size_pretty(table_len) AS table_size,
       round(approx_tuple_percent::numeric, 1) AS live_pct,
       round(dead_tuple_percent::numeric, 1) AS dead_pct,
       round(approx_free_percent::numeric, 1) AS free_pct
FROM pgstattuple_approx('orders');

-- Exact measurement: reads the whole table
SELECT pg_size_pretty(table_len) AS table_size,
       round(dead_tuple_percent::numeric, 1) AS dead_pct,
       round(free_percent::numeric, 1) AS free_pct,
       pg_size_pretty(dead_tuple_len + free_space) AS reclaimable
FROM pgstattuple('orders');

-- B-tree indexes: leaf density (~90 when freshly built; below 50 is bloated)
WITH idx AS MATERIALIZED (
  SELECT i.indexrelid
  FROM pg_index i
  JOIN pg_class c ON c.oid = i.indexrelid
  JOIN pg_am am ON am.oid = c.relam
  WHERE am.amname = 'btree' AND i.indrelid = 'orders'::regclass
)
SELECT idx.indexrelid::regclass AS index_name,
       pg_size_pretty(s.index_size) AS index_size,
       s.avg_leaf_density,
       s.leaf_fragmentation
FROM idx
CROSS JOIN LATERAL pgstatindex(idx.indexrelid) s;

Что делает

Показывает процент живых/мёртвых кортежей и свободного пространства таблицы (быстрая оценка и точное значение) и возвращаемое пространство; для B-tree индексов — плотность листовых страниц и фрагментацию.

Когда использовать

Когда оценки n_dead_tup в pg_stat_user_tables недостаточно; чтобы подкрепить данными решение о pg_repack, VACUUM FULL или REINDEX.

Внимание

pgstattuple и pgstatindex читают отношение целиком и создают высокую нагрузку I/O на больших таблицах (берут только AccessShareLock). Сначала используйте pgstattuple_approx. По умолчанию требуется суперпользователь или роль pg_stat_scan_tables. Некоторое свободное пространство — норма (fillfactor, место для HOT-обновлений); VACUUM делает его повторно используемым, но не уменьшает файл; для возврата нужен pg_repack или VACUUM FULL (блокировка ACCESS EXCLUSIVE!). Индекс с низким avg_leaf_density перестройте через REINDEX CONCURRENTLY.

Открыть в DBAtlas →

Связанные материалы