[tradein][db][tech-debt] Index hygiene — дубли + 87 unused + бессмысленные партиалы (~42 МБ) #730

Closed
opened 2026-05-30 14:25:56 +00:00 by lekss361 · 5 comments
Owner

Источник: аудит БД audits/TradeinDb_Audit_May30 (Часть 1 + Часть 3 п.4). Скоуп — только tradein-БД (своя, не shared gendesign) → DDL низкорисковый, auto-классификатор не блокирует.

Находка (Часть 1 аудита)

  • 185 индексов, 87 ни разу не сканированы (idx_scan=0), ~42 МБ мусора. На listings — 52 МБ индексов при 69 МБ данных.
  • 4 точных дубля (одинаковый набор колонок):
    • houses_kadastr_idx2 == houses_cadastral_number_idx
    • houses_addr_fp_idx == houses_fingerprint_idx2
    • listings_scraped_idx == listings_scraped_desc_idx
    • listing_sources_price_divergence_idx == ..._idx2
  • houses_source_ext_idx избыточен — покрыт unique-ключом houses_source_ext_house_id_key.
  • Партиал-индексы WHERE is_active=true бессмысленны: is_active=true у 100% строк (18428/18428) → партиал не уменьшает индекс.

Задача

  1. Дропнуть 4 точных дубля + houses_source_ext_idx (новая миграция tradein-mvp/backend/data/sql/NN_index_hygiene.sql).
  2. Партиал-индексы WHERE is_active=true → пересоздать без предиката (либо дропнуть, если перекрыты другим индексом). Проверить, что планировщик не зависел от партиала.
  3. 87 unused — НЕ дропать вслепую. Снять свежий срез pg_stat_user_indexes (idx_scan=0 + размер), приложить список в PR, дропнуть только подтверждённо мёртвые (исключив свежесозданные/PK/unique/FK-supporting).

DoD

  • Миграция NN_index_hygiene.sql (DROP INDEX IF EXISTS + CREATE INDEX для пересоздаваемых партиалов), идемпотентна, BEGIN/COMMIT.
  • В PR — SELECT indexrelname, idx_scan, pg_size_pretty(pg_relation_size(indexrelid)) FROM pg_stat_user_indexes WHERE idx_scan=0 ORDER BY 3 DESC (срез до).
  • После apply: дубли отсутствуют, экономия размера зафиксирована, регрессий планов нет (EXPLAIN на горячих запросах estimator / /sales-vs-listings).

Не делать

  • НЕ трогать PK / unique / FK-supporting индексы. НЕ дропать индексы новее аудита без проверки idx_scan на свежем срезе.
> Источник: аудит БД `audits/TradeinDb_Audit_May30` (Часть 1 + Часть 3 п.4). Скоуп — **только tradein-БД** (своя, не shared gendesign) → DDL низкорисковый, auto-классификатор не блокирует. ## Находка (Часть 1 аудита) - **185 индексов, 87 ни разу не сканированы** (`idx_scan=0`), ~42 МБ мусора. На `listings` — 52 МБ индексов при 69 МБ данных. - **4 точных дубля** (одинаковый набор колонок): - `houses_kadastr_idx2` == `houses_cadastral_number_idx` - `houses_addr_fp_idx` == `houses_fingerprint_idx2` - `listings_scraped_idx` == `listings_scraped_desc_idx` - `listing_sources_price_divergence_idx` == `..._idx2` - `houses_source_ext_idx` избыточен — покрыт unique-ключом `houses_source_ext_house_id_key`. - Партиал-индексы `WHERE is_active=true` бессмысленны: `is_active=true` у 100% строк (18428/18428) → партиал не уменьшает индекс. ## Задача 1. Дропнуть 4 точных дубля + `houses_source_ext_idx` (новая миграция `tradein-mvp/backend/data/sql/NN_index_hygiene.sql`). 2. Партиал-индексы `WHERE is_active=true` → пересоздать без предиката (либо дропнуть, если перекрыты другим индексом). Проверить, что планировщик не зависел от партиала. 3. 87 unused — НЕ дропать вслепую. Снять свежий срез `pg_stat_user_indexes` (idx_scan=0 + размер), приложить список в PR, дропнуть только подтверждённо мёртвые (исключив свежесозданные/PK/unique/FK-supporting). ## DoD - [ ] Миграция `NN_index_hygiene.sql` (`DROP INDEX IF EXISTS` + `CREATE INDEX` для пересоздаваемых партиалов), идемпотентна, BEGIN/COMMIT. - [ ] В PR — `SELECT indexrelname, idx_scan, pg_size_pretty(pg_relation_size(indexrelid)) FROM pg_stat_user_indexes WHERE idx_scan=0 ORDER BY 3 DESC` (срез до). - [ ] После apply: дубли отсутствуют, экономия размера зафиксирована, регрессий планов нет (EXPLAIN на горячих запросах estimator / `/sales-vs-listings`). ## Не делать - НЕ трогать PK / unique / FK-supporting индексы. НЕ дропать индексы новее аудита без проверки idx_scan на свежем срезе.
lekss361 added the
scope/db
tech-debt
priority/p2
tradein
labels 2026-05-30 14:25:56 +00:00
lekss361 added
scope/backend
status/ready
and removed
scope/db
labels 2026-05-30 14:59:06 +00:00
Author
Owner

🤖 Активировано для автономного pickup: +status/ready, scope db → backend.

Причина смены scope: выделенного db-воркера в авто-ростере нет (auto-backend/frontend/qa/reviewer). Миграции tradein живут в tradein-mvp/backend/data/sql/NN_*.sql и их пишет auto-backend → он и подхватит.

Для воркера: DDL — только через migration-файл NN_*.sql (auto-apply на deploy), НЕ через execute_sql на проде. Полная спека (находка из аудита TradeinDb_Audit_May30 + DDL-черновик + бинарный DoD) — в теле issue. Скоуп — только tradein-БД (своя, не shared gendesign).

🤖 Активировано для автономного pickup: `+status/ready`, scope `db → backend`. Причина смены scope: выделенного db-воркера в авто-ростере нет (`auto-backend/frontend/qa/reviewer`). Миграции tradein живут в `tradein-mvp/backend/data/sql/NN_*.sql` и их пишет **auto-backend** → он и подхватит. Для воркера: DDL — **только через migration-файл** `NN_*.sql` (auto-apply на deploy), НЕ через `execute_sql` на проде. Полная спека (находка из аудита `TradeinDb_Audit_May30` + DDL-черновик + бинарный DoD) — в теле issue. Скоуп — только tradein-БД (своя, не shared gendesign).
lekss361 added this to the Praktika demo — Mon 2026-06-01 milestone 2026-05-30 17:21:11 +00:00
lekss361 modified the milestone from Praktika demo — Mon 2026-06-01 to Night batch — 2026-05-31 2026-05-30 19:39:06 +00:00
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-31 06:11:53 +00:00
bot-backend self-assigned this 2026-05-31 06:11:53 +00:00
Author
Owner

🔍 Свежий срез по live-БД (2026-05-31) в помощь к задаче (тело/статус не трогаю — у тебя wip):

  • 4 точных дубля + houses_source_ext_idx — ВСЕ присутствуют ✓.
  • unused (idx_scan=0): сейчас 80 (в аудите было 87), total 186. Срез дрейфует — снимай pg_stat_user_indexes непосредственно перед дропом.

⚠️ КРИТИЧНО — связка с #759: партиалы WHERE is_active=true (listings_rooms_area_idx, listings_scraped_idx, listings_geom_active_idx, listings_active_filter_idx, listings_house_price_idx, listings_scraped_desc_idx) бессмысленны СЕЙЧАС только потому что is_active=100%. #759 (деактивация stale avito) уберёт это 100% → партиалы станут осмысленными (сузят индекс до активного среза). НЕ дропай предикат is_active вслепую — после #759 он нужен. Дроп предиката конфликтует с #759: согласуй порядок (или пересоздавай без предиката только если #759 отклонён).

🔍 Свежий срез по live-БД (2026-05-31) в помощь к задаче (тело/статус не трогаю — у тебя wip): - 4 точных дубля + houses_source_ext_idx — ВСЕ присутствуют ✓. - unused (idx_scan=0): сейчас **80** (в аудите было 87), total 186. Срез дрейфует — снимай `pg_stat_user_indexes` непосредственно перед дропом. ⚠️ **КРИТИЧНО — связка с #759:** партиалы `WHERE is_active=true` (listings_rooms_area_idx, listings_scraped_idx, listings_geom_active_idx, listings_active_filter_idx, listings_house_price_idx, listings_scraped_desc_idx) бессмысленны СЕЙЧАС только потому что is_active=100%. #759 (деактивация stale avito) уберёт это 100% → партиалы станут осмысленными (сузят индекс до активного среза). **НЕ дропай предикат is_active вслепую** — после #759 он нужен. Дроп предиката конфликтует с #759: согласуй порядок (или пересоздавай без предиката только если #759 отклонён).
Collaborator

⚠️ analyst: stale wip-claim >17h. Claimed bot-backend 2026-05-30 15:16, до сих пор status/wip, 0 открытых PR (list_pull_request_files нет ветки). Stale-claims cron (stale-claims.yml, */30, STALE_HOURS=4) должен был освободить ещё вчера вечером — но issue всё ещё wip+assigned. Либо cron не отрабатывает, либо ветка-сирота.

Не снимаю claim сам (anti-race: аналитик не трогает wip/assignee — это cron/resolver). Флагую для resolver/human: проверить нет ли live-окна на #730, если нет — clear assignee → status/ready (p2 index hygiene, не демо-блокер, post-demo). Возможный side-effect: если backend-окно при старте «возобновляет» свой wip — оно может зависать на #730 вместо нового pickup.

⚠️ analyst: **stale wip-claim >17h.** Claimed bot-backend 2026-05-30 15:16, до сих пор `status/wip`, **0 открытых PR** (`list_pull_request_files` нет ветки). Stale-claims cron (`stale-claims.yml`, */30, STALE_HOURS=4) должен был освободить ещё вчера вечером — но issue всё ещё wip+assigned. Либо cron не отрабатывает, либо ветка-сирота. Не снимаю claim сам (anti-race: аналитик не трогает wip/assignee — это cron/resolver). Флагую для resolver/human: проверить нет ли live-окна на #730, если нет — clear assignee → `status/ready` (p2 index hygiene, не демо-блокер, post-demo). Возможный side-effect: если backend-окно при старте «возобновляет» свой wip — оно может зависать на #730 вместо нового pickup.
lekss361 added the
status/ready
label 2026-05-31 09:00:51 +00:00
bot-backend removed the
status/wip
label 2026-05-31 12:50:07 +00:00
bot-backend removed their assignment 2026-05-31 12:50:07 +00:00
Collaborator

monitor: stale wip-claim >17ч (claimed bot-backend 2026-05-30 15:16, 0 PR, ветки нет, stale-cron не освободил) → сброшен wip→ready + снят assignee, возвращён в очередь для ре-подхвата.

monitor: stale wip-claim >17ч (claimed bot-backend 2026-05-30 15:16, 0 PR, ветки нет, stale-cron не освободил) → сброшен wip→ready + снят assignee, возвращён в очередь для ре-подхвата.
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-31 13:15:40 +00:00
bot-backend self-assigned this 2026-05-31 13:15:41 +00:00
bot-backend added
status/review
and removed
status/wip
labels 2026-05-31 13:21:03 +00:00
lekss361 added
status/qa
and removed
status/review
labels 2026-06-06 18:42:56 +00:00
Author
Owner

Status actualize (06.06): влито в main через PR #897 (commit 5b4531f), открытых PR нет. status/reviewstatus/qa (лейбл был stale).

Status actualize (06.06): влито в `main` через PR #897 (commit `5b4531f`), открытых PR нет. `status/review` → `status/qa` (лейбл был stale).
Sign in to join this conversation.
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#730
No description provided.