---
name: db-performance
description: "Диагностика производительности БД и запросов 1С. Используй когда нужно диагностировать медленный сценарий, slow query, план СУБД, блокировки, deadlock, TEMPDB/WAL, размеры таблиц или СКД на больших данных."
target_agents:
  - debugger
  - developer-code
  - architect
---

# DB Performance — диагностика производительности БД

Навык работает на **двух уровнях одновременно**: платформа 1С (запрос, метаданные, СКД) и СУБД (план, локи, ожидания, temp storage). Диагноз без обоих уровней — неполный.

---

## Когда применять

| Симптом | Первый шаг |
|---------|-----------|
| Медленный отчёт / проведение / обмен | Шаг 1: назвать сценарий |
| SQL в ТЖ с большим `Duration` | Шаг 2: извлечь запрос + метаданные |
| Блокировки `TLOCK` / `TDEADLOCK` | Шаг 3: собрать СУБД-evidence |
| TEMPDB/WAL растёт при «только чтение» | Шаги 3-4: red flags + причины |
| Таблица выросла — отчёт стал медленнее | Полный алгоритм (шаги 1-5) |

Этот навык — **нижний доказательный слой**. Для переписывания текста запроса или СКД — передать в `query-optimize`.

---

## Инструменты

| Задача | Инструмент |
|--------|-----------|
| Поиск запроса в коде | `rg` (ripgrep) по тексту BSL |
| Навигация к символу / процедуре | `code-navigation` |
| Получить SQL из ТЖ | `tech-log-analysis` → `search_tech_log` с `name: DBMSSQL` / `DBPOSTGRS` |
| Прогон теста / синтаксис | `v8-runner` |
| Информация о метаданных | `code-navigation` → структура регистра / справочника |

Нет прямого доступа к `EXPLAIN ANALYZE`, `pg_stat_statements`, `sys.dm_exec_query_stats` — инструкции по получению передаются пользователю/администратору.

---

## Алгоритм (5 шагов)

### Шаг 1. Назвать сценарий

Точно определить: что делает пользователь / какой фоновый процесс / какой шаг обмена / какой отчёт с какими отборами. Без конкретного сценария диагностика невозможна.

Зафиксировать: *название*, *ожидаемое время*, *фактическое время*, *условия* (объём данных, организация, период).

### Шаг 2. Извлечь запрос + метаданные

**Платформенный слой:**
- Найти текст запроса в BSL: `rg "Запрос.Текст\s*=" --type-add "bsl:*.bsl" -t bsl`
- Для СКД — найти `.xml` схемы компоновки данных через `code-navigation`
- Проверить метаданные: тип регистра (накопления / сведений), периодичность, ресурсы, измерения, табличные части
- Зафиксировать: контекст вызова, граница транзакции, цикл вокруг запроса, параметры виртуальных таблиц

**Требование:** текст запроса 1С **обязательно в паре** с хотя бы одним СУБД-артефактом (шаг 3). Анализ только текста запроса без СУБД-evidence не даёт доказательной базы.

### Шаг 3. Собрать СУБД-evidence

Категории доказательств (нужна хотя бы одна):

| Категория | PostgreSQL | MS SQL Server | Что доказывает |
|-----------|-----------|---------------|----------------|
| **План запроса** | `EXPLAIN (ANALYZE, BUFFERS)` | `SET STATISTICS IO, TIME ON` + actual plan | Seq scan vs index scan, hash join cost, actual rows |
| **Блокировки / ожидания** | `pg_locks`, `pg_stat_activity` | `sys.dm_exec_requests`, `sys.dm_os_waiting_tasks` | Lock holder, waiter, тип блокировки |
| **Temp storage** | WAL size, `pg_stat_bgwriter` | TEMPDB usage, VLF count | Скрытая запись при «только чтение» |
| **Статистика таблиц** | `pg_stat_user_tables` | `sys.dm_db_index_usage_stats` | Seq scans vs index seeks, stale stats |
| **ТЖ-артефакты** | `DBPOSTGRS` events | `DBMSSQL` events | Duration, SQL текст, context |

Файловая ИБ — отдельная модель: нет СУБД-плана, производительность определяется структурой dbf-файлов, блокировки через платформенный менеджер.

**Правило missing evidence:** если СУБД-артефакт получить невозможно — зафиксировать явно: «СУБД-evidence отсутствует, причина: <...>». Не заменять предположениями.

### Шаг 4. Разделить причины

Классифицировать причину по категории:

| Категория | Признаки |
|-----------|---------|
| **Неэффективный запрос** | Seq scan на большой таблице, отсутствие фильтра в виртуальной таблице, dot-dereference без ВЫРАЗИТЬ |
| **Пропущенный / вредный индекс** | Full table scan по полю без индекса; или индекс есть, но не используется из-за типа условия |
| **Широкое чтение виртуальной таблицы** | `Остатки()` без параметров периода / измерений |
| **Query-in-loop** | N запросов на N строк: `Duration * N` в ТЖ, повторяющийся SQL с разными параметрами |
| **Lock contention** | `TLOCK` / `TDEADLOCK` в ТЖ; блокирующий запрос в `pg_locks` / `sys.dm_exec_requests` |
| **СУБД-обслуживание** | Autovacuum, index rebuild, статистика устарела — план деградировал |
| **Рост данных** | Запрос корректен, но объём таблицы вырос — план поменялся |

Одна причина на итерацию. Если причин несколько — начать с наиболее вероятной по evidence.

### Шаг 5. Одно измеримое изменение + верификация

- Предложить **одно** изменение: переписать запрос / добавить параметр виртуальной таблицы / добавить индекс / переместить запрос из цикла
- Для каждого изменения — ожидаемый эффект измеримо: «Duration снизится с X до Y» / «Seq scan заменится на Index Seek»
- Верификация: прогон того же сценария + сравнение СУБД-evidence до и после
- Синтаксис — через `v8-runner`

---

## Stop rules

1. **Не рекомендовать индекс без** конкретного предиката / JOIN / сортировки / группировки + оценки write-cost tradeoff.
2. **Не убирать `РАЗРЕШЕННЫЕ`** и не отключать RLS/фильтры прав ради производительности без явного согласования безопасности.
3. **Не утверждать причину на уровне СУБД без СУБД-evidence.** Зафиксировать missing evidence.
4. **Не обобщать** PostgreSQL-специфичный вывод на MS SQL Server и наоборот.
5. **Не предлагать несколько изменений одновременно** — невозможно измерить вклад каждого.

---

## Модели доказательств по СУБД

### PostgreSQL
- Основной инструмент: `EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)`
- Паттерны проблем: Seq Scan на таблице > 100K строк, Hash Join с большим `rows=`, высокий `shared hit` при малом `actual rows`
- Temp files: `work_mem` переполнен → temp file в плане → WAL pressure
- Блокировки: `pg_stat_activity.wait_event_type = 'Lock'`

### MS SQL Server
- Основной инструмент: Actual Execution Plan + `SET STATISTICS IO ON`
- Паттерны: Table Scan / Clustered Index Scan вместо Seek, Key Lookup, Implicit conversion из-за типов
- TEMPDB: spill to disk в Sort / Hash Match → `tempdb.sys.dm_db_task_space_usage`
- Блокировки: `sys.dm_exec_requests.blocking_session_id`

### Файловая ИБ
- Нет СУБД-плана
- Производительность зависит от размера dbf-файлов и платформенных индексов
- Блокировки — платформенный механизм, виден в ТЖ (`TLOCK`)
- Рекомендация: миграция на клиент-серверный вариант при росте объёма

---

## Вывод (формат ответа)

```
## Сценарий и evidence
<Сценарий: ...>
<СУБД-evidence: план / ТЖ / отсутствует (причина)>

## Корневая причина (по убыванию вероятности)
1. <Категория> — <факт из evidence>
2. ...

## Изменение
<Одно конкретное изменение: текст / индекс / параметр>
<Ожидаемый измеримый эффект>

## Верификация
<Как измерить: команда / сценарий / сравнение ТЖ>

## Остаточные риски
<Объём данных / блокировки / СУБД-специфика>
```

---

## Red flags (немедленные маркеры)

- Отчёт фильтрует по дате / организации / тенанту **после** соединения больших таблиц
- Виртуальная таблица вызвана без параметров периода / измерений
- Один и тот же SQL в ТЖ повторяется N раз с разными параметрами (query-in-loop)
- Долгие локи совпадают с большими записями: проведение, обмен, фоновые задания
- Temp storage или лог транзакций растёт при «только чтение» сценарии

---

depends_on:
  - framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md
  - framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md
  - framework/skills/tool-usage/v8-runner/SKILL.md
  - framework/skills/bsl-practices/query-optimize/SKILL.md
---
