docs(db): add postgres schema diagnostics runbook
Runbook для оценки размеров таблиц, seq scan и EXPLAIN перед/после миграций схемы. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# Диагностика схемы PostgreSQL (EvoBGP)
|
||||
|
||||
Runbook для оценки объёма БД и узких мест **перед** и **после** миграций оптимизации схемы. Выполнять на staging или production read-only сессией.
|
||||
|
||||
## Подключение
|
||||
|
||||
```bash
|
||||
psql "$EVOBGP_DATABASE_URL"
|
||||
```
|
||||
|
||||
## 1. Размеры таблиц и индексов
|
||||
|
||||
```sql
|
||||
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 (горячие таблицы)
|
||||
|
||||
```sql
|
||||
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. Неиспользуемые индексы
|
||||
|
||||
```sql
|
||||
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)`:
|
||||
|
||||
```sql
|
||||
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 для типовых запросов
|
||||
|
||||
```sql
|
||||
-- Список префиксов ревизии (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 на больших таблицах.
|
||||
Reference in New Issue
Block a user