feat(db): GiST по (geom::geography) на houses — матчинг идёт по индексу (#2997) #3020

Merged
bot-backend merged 1 commit from feat/2997-houses-geog-index into main 2026-08-21 10:24:36 +00:00
Collaborator

Summary

  • Миграция 270_houses_geog_gist_idx.sql: CREATE INDEX CONCURRENTLY houses_geog_gist_idx ON houses USING gist ((geom::geography)) — под ST_DWithin(geom::geography, …) матчинга (matching/houses.py:300/352/554). Сейчас планировщик берёт houses_geom_idx только как bitmap по geom IS NOT NULL и фильтрует все ~9.4k строк.
  • До (прод 21.08, EXPLAIN ANALYZE, центр ЕКБ, 150 м): Bitmap Index Scan on houses_geom_idx · Index Cond: (geom IS NOT NULL) · Rows Removed by Filter: 4718 · Execution Time: 70.7 ms; pg_stat_statements за 13 ч: 66 × 39.9 мс + 5 × 53.3 мс.
  • Без BEGIN/COMMIT по образцу 225 (CIC нельзя в транзакции; раннер деплоя — psql autocommit по операторам; гейт lock_timeout CONCURRENTLY-формы пропускает — проверено локально: ✓ 25 миграций).
  • Не трогаю houses_geom_idx и дубль listings_geom_idx: в pg_stat_statements нашёлся живой потребитель listings.geom как geometry (ST_DWithin(cb.geom, l.geom, …) в сшивке с cad_buildings_local) — постановка «потребителей нет» неполная, дроп требует отдельного разбора. Напишу в issue.

Test plan

  • scripts/check-migration-lock-timeout.py ✓; test_migration_numbering.py 3 passed (270 — следующий после 269 на origin/main).
  • После деплоя: \di houses_geog_gist_idx валиден; EXPLAIN ANALYZE того же запроса — Index Scan using houses_geog_gist_idx, время в единицах мс; в комментарии к #2997 до/после.
  • Шаг проверки невалидных индексов деплоя зелёный.

Refs #2997

## Summary - Миграция `270_houses_geog_gist_idx.sql`: `CREATE INDEX CONCURRENTLY houses_geog_gist_idx ON houses USING gist ((geom::geography))` — под `ST_DWithin(geom::geography, …)` матчинга (`matching/houses.py:300/352/554`). Сейчас планировщик берёт `houses_geom_idx` только как bitmap по `geom IS NOT NULL` и фильтрует все ~9.4k строк. - **До (прод 21.08, EXPLAIN ANALYZE, центр ЕКБ, 150 м):** `Bitmap Index Scan on houses_geom_idx · Index Cond: (geom IS NOT NULL) · Rows Removed by Filter: 4718 · Execution Time: 70.7 ms`; `pg_stat_statements` за 13 ч: 66 × 39.9 мс + 5 × 53.3 мс. - Без BEGIN/COMMIT по образцу 225 (CIC нельзя в транзакции; раннер деплоя — psql autocommit по операторам; гейт lock_timeout CONCURRENTLY-формы пропускает — проверено локально: ✓ 25 миграций). - **Не трогаю** `houses_geom_idx` и дубль `listings_geom_idx`: в `pg_stat_statements` нашёлся живой потребитель `listings.geom` как geometry (`ST_DWithin(cb.geom, l.geom, …)` в сшивке с `cad_buildings_local`) — постановка «потребителей нет» неполная, дроп требует отдельного разбора. Напишу в issue. ## Test plan - [x] `scripts/check-migration-lock-timeout.py` ✓; `test_migration_numbering.py` 3 passed (270 — следующий после 269 на origin/main). - [ ] После деплоя: `\di houses_geog_gist_idx` валиден; EXPLAIN ANALYZE того же запроса — `Index Scan using houses_geog_gist_idx`, время в единицах мс; в комментарии к #2997 до/после. - [ ] Шаг проверки невалидных индексов деплоя зелёный. Refs #2997
bot-backend added 1 commit 2026-08-21 10:18:24 +00:00
feat(db): GiST по (geom::geography) на houses — матчинг идёт по индексу (#2997)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m15s
2f7b22f659
Почему: весь матчинг домов — ST_DWithin(geom::geography, …), а единственный
пространственный индекс houses_geom_idx построен по geometry. Планировщик
берёт его лишь как bitmap по geom IS NOT NULL и фильтрует все ~9.4k строк:
70.7 мс на запрос (EXPLAIN ANALYZE на проде 21.08), 66+5 вызовов за 13 ч по
pg_stat_statements. При росте справочника ×8.5 это главное узкое место
матчинга (#2997).

Что: миграция 270 — CREATE INDEX CONCURRENTLY houses_geog_gist_idx
USING gist ((geom::geography)); без BEGIN/COMMIT по образцу 225 (CIC не
живёт в транзакции; раннер деплоя — psql autocommit по операторам).
houses_geom_idx и дубль на listings не трогаю: в pg_stat_statements есть
живой потребитель listings.geom как geometry (сшивка с cad_buildings_local)
— дроп требует отдельного разбора.

Проверка: EXPLAIN ANALYZE до/после на проде — в комментарии к #2997.

Refs #2997
bot-backend merged commit fa32db299d into main 2026-08-21 10:24:36 +00:00
bot-backend deleted branch feat/2997-houses-geog-index 2026-08-21 10:24:36 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#3020
No description provided.