Runbook для оценки размеров таблиц, seq scan и EXPLAIN перед/после миграций схемы. Co-authored-by: Cursor <cursoragent@cursor.com>
91 lines
2.7 KiB
Markdown
91 lines
2.7 KiB
Markdown
# Диагностика схемы 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 на больших таблицах.
|