perf(sql): geography GIST + covering index для analyze-пути Site Finder (157) #1334

Merged
bot-backend merged 1 commit from perf/analyze-hotpath-indexes into main 2026-06-14 16:45:23 +00:00
Collaborator

Summary (perf, Refs #70)

EXPLAIN ANALYZE на проде: горячий analyze-путь Site Finder делал Seq Scan на каждый запрос — фильтры по X.geom::geography (метровый ST_DWithin) не могут использовать существующие GIST на плоском geom. 4 индекса:

таблица запрос до → после
cad_buildings (88МБ) соседи 100м 314мс → 0.3мс
osm_noise_sources_ekb noise/hydro/util (×4/analyze) 92мс → 3.8мс
osm_poi_ekb POI 1км 36мс → 0.2мс
objective_lots (2.1ГБ) competitor pricing 493мс → 355мс (Index Only Scan, −13× buffers)
  • 3 функциональных GIST (geom::geography) + 1 covering (project_name) INCLUDE(price_per_m2_rub, area_pd, is_sold).
  • Плоские geom-GIST НЕ дублируются (обслуживают ST_Intersects-ветки) — сохранены.
  • Lock SHARE (блокирует только writes/ETL, читателей analyze НЕ блокирует), build ~2.2с (как прецедент 153). Idempotent (IF NOT EXISTS).

Test plan

  • EXPLAIN до/после в BEGIN…ROLLBACK на проде (прод не мутирован)
  • миграция целиком прогнана транзакционно ON_ERROR_STOP → ROLLBACK
  • не добавлены redundant (rosreestr_deals/pipeline/permits уже покрыты)
  • database-expert (специалист)
  • post-deploy: VACUUM ANALYZE + подтвердить Index Scan на analyze

Follow-up (вне scope, backend)

query obj_pricing сканирует ВСЕ objective_lots вместо ~245 ближних — пушдаун domrf_obj_id IN (nearby) в parcels.py даст ещё ×10.

Refs #70

## Summary (perf, Refs #70) EXPLAIN ANALYZE на проде: горячий analyze-путь Site Finder делал **Seq Scan на каждый запрос** — фильтры по `X.geom::geography` (метровый ST_DWithin) не могут использовать существующие GIST на плоском `geom`. 4 индекса: | таблица | запрос | до → после | |---|---|---| | cad_buildings (88МБ) | соседи 100м | **314мс → 0.3мс** | | osm_noise_sources_ekb | noise/hydro/util (**×4**/analyze) | 92мс → 3.8мс | | osm_poi_ekb | POI 1км | 36мс → 0.2мс | | objective_lots (2.1ГБ) | competitor pricing | 493мс → 355мс (Index Only Scan, −13× buffers) | - 3 функциональных GIST `(geom::geography)` + 1 covering `(project_name) INCLUDE(price_per_m2_rub, area_pd, is_sold)`. - Плоские geom-GIST НЕ дублируются (обслуживают ST_Intersects-ветки) — сохранены. - **Lock SHARE** (блокирует только writes/ETL, читателей analyze НЕ блокирует), build ~2.2с (как прецедент 153). Idempotent (IF NOT EXISTS). ## Test plan - [x] EXPLAIN до/после в BEGIN…ROLLBACK на проде (прод не мутирован) - [x] миграция целиком прогнана транзакционно ON_ERROR_STOP → ROLLBACK - [x] не добавлены redundant (rosreestr_deals/pipeline/permits уже покрыты) - [x] database-expert (специалист) - [ ] post-deploy: VACUUM ANALYZE + подтвердить Index Scan на analyze ## Follow-up (вне scope, backend) query obj_pricing сканирует ВСЕ objective_lots вместо ~245 ближних — пушдаун `domrf_obj_id IN (nearby)` в `parcels.py` даст ещё ×10. Refs #70
bot-backend added 1 commit 2026-06-14 16:33:31 +00:00
perf(sql): geography GIST + covering index для горячего analyze-пути SF (157)
All checks were successful
CI / changes (push) Successful in 6s
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Successful in 1m56s
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (push) Successful in 8m54s
CI / openapi-codegen-check (pull_request) Successful in 1m51s
CI / backend-tests (pull_request) Successful in 8m36s
904e945035
EXPLAIN ANALYZE на проде выявил Seq Scan на каждый analyze из-за geom::geography
предикатов (плоский geom-GIST не применим). 4 индекса:
- osm_poi_ekb/osm_noise_sources_ekb/cad_buildings geography GIST:
  POI 36->0.2мс, noise 92->3.8мс (4x/analyze), соседи 314->0.3мс
- objective_lots(project_name) INCLUDE(price,area,is_sold): competitor 493->355мс
Lock SHARE (writes-only, читателей analyze не блокирует), build ~2.2с (как 153).
Idempotent (IF NOT EXISTS).

Refs #70
bot-backend merged commit 5bf30570a5 into main 2026-06-14 16:45:23 +00:00
bot-backend deleted branch perf/analyze-hotpath-indexes 2026-06-14 16:45:23 +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#1334
No description provided.