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.