Updated the PostgreSQL monitoring service to improve handling of `pg_stat_statements` availability. Introduced a new method to check if the extension is queryable and updated the response structure to include availability status and hints. Enhanced the documentation to clarify the requirements for enabling `pg_stat_statements`. Adjusted related components to reflect these changes, ensuring better user feedback in the monitoring interface.
4.0 KiB
Диагностика схемы PostgreSQL (EvoBGP)
Runbook для оценки объёма БД и узких мест перед и после миграций оптимизации схемы. Выполнять на staging или production read-only сессией.
Подключение
psql "$EVOBGP_DATABASE_URL"
HTTP API (панель / мониторинг)
При подключённом PostgreSQL control plane отдаёт instance-level метрики (роль viewer+):
GET /v1/monitoring/postgres/overview— подключения, TPS, cache hit, размер БДGET /v1/monitoring/postgres/queries— top queries (pg_stat_statements, если extension включён)GET /v1/monitoring/postgres/locks,/tables,/recommendationsGET /v1/monitoring/correlation?window=60— корреляция refresh jobs и cache hit
Обслуживание (operator, async 202 + job_id): POST /v1/postgres/vacuum, vacuum-analyze, analyze, reindex, cleanup; журнал GET /v1/postgres/maintenance/logs.
CLI на CP: evobgp-api db report|vacuum|analyze|cleanup (см. internal/dbcli).
Миграция 000023 создаёт pg_stat_statements; для сбора статистики обязательно preload и перезапуск Postgres:
# postgresql.conf или command в compose
shared_preload_libraries = 'pg_stat_statements'
После изменения — restart контейнера/сервиса Postgres. Без этого API /v1/monitoring/postgres/queries вернёт пустой список (statements_available: false), без 5xx.
1. Размеры таблиц и индексов
SELECT relname,
pg_size_pretty(pg_total_relation_size(relid)) AS total,
pg_size_pretty(pg_relation_size(relid)) AS heap,
pg_size_pretty(pg_indexes_size(relid)) AS indexes
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
Ожидание: лидеры — revision_materialized_prefix, config_revision (TOAST от preview), JSONB-кэши.
2. Seq scan (горячие таблицы)
SELECT schemaname, relname, seq_scan, seq_tup_read, idx_scan
FROM pg_stat_user_tables
WHERE schemaname = 'public'
ORDER BY seq_tup_read DESC;
Сброс статистики после деплоя: SELECT pg_stat_reset(); (только осознанно, теряется baseline).
3. Неиспользуемые индексы
SELECT indexrelname, idx_scan, pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
WHERE schemaname = 'public' AND idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
4. Дубликаты в materialized prefixes
Перед UNIQUE (revision_id, prefix, community_id, source):
SELECT revision_id, prefix, community_id, source, COUNT(*) AS n
FROM revision_materialized_prefix
GROUP BY 1, 2, 3, 4
HAVING COUNT(*) > 1
LIMIT 20;
5. Шаблон отчёта staging
| Метрика | До | После | Дата |
|---|---|---|---|
revision_materialized_prefix total |
|||
config_revision total |
|||
module_prefix_snapshot total |
|||
asn_prefix_cache total |
|||
| Top seq_scan table | |||
| Unused indexes (count) |
6. EXPLAIN для типовых запросов
-- Список префиксов ревизии (keyset)
EXPLAIN (ANALYZE, BUFFERS)
SELECT prefix::text, community_id::text, source
FROM revision_materialized_prefix
WHERE revision_id = '<revision-uuid>'::uuid
ORDER BY id
LIMIT 51;
-- Diff added (anti-join)
EXPLAIN (ANALYZE, BUFFERS)
SELECT b.prefix::text
FROM revision_materialized_prefix b
LEFT JOIN revision_materialized_prefix a
ON a.revision_id = '<rev-a>'::uuid AND a.prefix = b.prefix
WHERE b.revision_id = '<rev-b>'::uuid
AND a.prefix IS NULL
ORDER BY b.prefix
LIMIT 5001;
Цель: Index Scan / Bitmap Index Scan по (revision_id, …), без Seq Scan на больших таблицах.