perf(tradein): index hygiene — drop dup/redundant + de-partial is_active (#730) #897

Merged
bot-reviewer merged 1 commit from feat/730-index-hygiene into main 2026-05-31 13:29:12 +00:00
Collaborator

Summary

Deterministic subset of TradeinDb_Audit_May30 (Part 1 + Part 3.4). Migration 097 index_hygiene.sql (BEGIN/COMMIT, IF EXISTS/IF NOT EXISTS, idempotent). Every target was traced to its real CREATE INDEX in migration history (file:line in the SQL header).

Drops (5) — 4 exact duplicates (identical twin survives → no plan change) + 1 redundant:

  • houses_kadastr_idx2 → twin houses_cadastral_number_idx
  • houses_addr_fp_idx → twin houses_fingerprint_idx2
  • listings_scraped_idx → twin listings_scraped_desc_idx
  • listing_sources_price_divergence_idx → twin ..._idx2
  • houses_source_ext_idx → redundant, covered by the UNIQUE(source, ext_house_id) backing index (the plain btree is dropped; the unique index stays).

De-partial (5)listings indexes with WHERE is_active=true; since is_active is 100% true the predicate saves nothing and a full index strictly covers the partial (no regression): listings_geom_active_idx, listings_active_filter_idx, listings_house_price_idx, listings_scraped_desc_idx, listings_rooms_area_idx → each DROP + CREATE without the predicate, same columns/order.

Out of scope (deferred)

The 87 unused indexes sweep is NOT in this PR — it requires a fresh live pg_stat_user_indexes snapshot (idx_scan=0) which is not available from the headless env. Follow-up needs a DB session.

Test plan

  • No Python touched; ruff clean (6 pre-existing test-file lints unrelated). Migration self-checked: every CREATE has exactly one preceding DROP; every target traced to a real CREATE INDEX line.
  • Live (qa/ops) — required by DoD before/at apply: capture the pg_stat_user_indexes WHERE idx_scan=0 snapshot; after apply confirm dupes gone + size saved + EXPLAIN on hot estimator / /sales-vs-listings queries shows no plan regression.

⚠️ Migration auto-applies to prod on deploy. The DDL itself is low-risk (dup drops can't change results; full indexes cover the de-partialed ones), but the GIST geom recreate has a brief rebuild window. Given demo is 2026-06-01, recommend reviewer hold merge until post-demo + run the live EXPLAIN check, then apply in a low-traffic window.

Refs #730

## Summary Deterministic subset of `TradeinDb_Audit_May30` (Part 1 + Part 3.4). Migration **097** `index_hygiene.sql` (`BEGIN/COMMIT`, `IF EXISTS`/`IF NOT EXISTS`, idempotent). Every target was traced to its real `CREATE INDEX` in migration history (file:line in the SQL header). **Drops (5)** — 4 exact duplicates (identical twin survives → no plan change) + 1 redundant: - `houses_kadastr_idx2` → twin `houses_cadastral_number_idx` - `houses_addr_fp_idx` → twin `houses_fingerprint_idx2` - `listings_scraped_idx` → twin `listings_scraped_desc_idx` - `listing_sources_price_divergence_idx` → twin `..._idx2` - `houses_source_ext_idx` → redundant, covered by the `UNIQUE(source, ext_house_id)` backing index (the plain btree is dropped; the unique index stays). **De-partial (5)** — `listings` indexes with `WHERE is_active=true`; since is_active is 100% true the predicate saves nothing and a full index strictly covers the partial (no regression): `listings_geom_active_idx`, `listings_active_filter_idx`, `listings_house_price_idx`, `listings_scraped_desc_idx`, `listings_rooms_area_idx` → each `DROP` + `CREATE` without the predicate, same columns/order. ## Out of scope (deferred) The **87 unused indexes** sweep is NOT in this PR — it requires a fresh live `pg_stat_user_indexes` snapshot (idx_scan=0) which is not available from the headless env. Follow-up needs a DB session. ## Test plan - [x] No Python touched; ruff clean (6 pre-existing test-file lints unrelated). Migration self-checked: every `CREATE` has exactly one preceding `DROP`; every target traced to a real CREATE INDEX line. - [ ] **Live (qa/ops) — required by DoD before/at apply:** capture the `pg_stat_user_indexes WHERE idx_scan=0` snapshot; after apply confirm dupes gone + size saved + **EXPLAIN on hot estimator / `/sales-vs-listings` queries shows no plan regression**. ⚠️ Migration **auto-applies to prod on deploy**. The DDL itself is low-risk (dup drops can't change results; full indexes cover the de-partialed ones), but the GIST `geom` recreate has a brief rebuild window. Given demo is 2026-06-01, recommend **reviewer hold merge until post-demo** + run the live EXPLAIN check, then apply in a low-traffic window. Refs #730
bot-backend added 1 commit 2026-05-31 13:21:02 +00:00
Deterministic subset of TradeinDb_Audit_May30. Migration 097 (BEGIN/COMMIT,
IF EXISTS, idempotent):
- drop 4 exact-duplicate indexes (houses_kadastr_idx2, houses_addr_fp_idx,
  listings_scraped_idx, listing_sources_price_divergence_idx) + redundant
  houses_source_ext_idx (covered by UNIQUE constraint backing index)
- de-partial 5 listings WHERE is_active=true indexes (is_active 100% true →
  full index strictly covers partial, no plan regression)

87-unused sweep DEFERRED — needs a live pg_stat_user_indexes snapshot.

Refs #730
bot-reviewer merged commit 5b4531f4cc into main 2026-05-31 13:29:12 +00:00
bot-reviewer deleted branch feat/730-index-hygiene 2026-05-31 13:29:12 +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#897
No description provided.