perf(objective_lots): drop 3 dead indexes (status/rooms_area/bank) — write-amp (#1953) #2056

Merged
bot-backend merged 1 commit from perf/drop-dead-objective-lots-indexes-1953 into main 2026-06-28 14:39:06 +00:00

1 commit

Author SHA1 Message Date
800e68af58 perf(objective_lots): drop 3 dead indexes to cut UPSERT write-amp (#1953)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m17s
CI / backend-tests (pull_request) Successful in 14m47s
perf-hunt finding #4: objective_lots is a hot UPSERT table (1.76M ins /
1.39M upd over 35d) — each write maintains every index. These three have
near-zero lifetime idx_scan AND no sargable consumer anywhere in the
backend/SQL, so they are pure write-amplification:

  - objective_lots_status_idx   (idx_scan=8,  19 MB) — consumers use
    LOWER(COALESCE(status,''))='продан', not sargable on plain B-tree
  - objective_lots_rooms_area_idx (idx_scan=7, 78 MB) — rooms_int/area_pd
    only in SELECT projections + CASE-bucket, never a WHERE/ORDER filter
  - objective_lots_bank_idx     (idx_scan=2,  8 KB) — bank_name only in an
    IS NOT NULL projection; WHERE bank_name= is a different table

Verified on prod: EXPLAIN of each real query shape → Seq Scan (index not
chosen even when present). Frees ~97 MB + per-write WAL/maintenance.
Idempotent (DROP INDEX IF EXISTS), BEGIN/COMMIT, dry-run clean.
Rollback: recreate from data/sql/68_schema_objective.sql:250-256.

NOT touched: project_name_trgm_idx (236 MB) — has an ETL consumer
(objective_backfill.py similarity()); needs separate ETL-cadence check.
2026-06-28 19:13:42 +05:00