-- 104_index_hygiene_geom_dedup.sql -- #730 index hygiene (follow-up to 097_index_hygiene.sql). -- -- Context: -- Issue #730 listed 5 duplicate/redundant indexes + 5 is_active=true partials to -- de-partial. ALL of those were already handled by 097_index_hygiene.sql, which is -- applied on prod (verified in _schema_migrations, 2026-06-13). Re-verification on -- prod confirms every audit target is already gone / already de-partialed: -- houses_kadastr_idx2, houses_addr_fp_idx, listings_scraped_idx, -- listing_sources_price_divergence_idx, houses_source_ext_idx -> ABSENT (dropped by 097) -- listings_geom_active_idx, listings_active_filter_idx, listings_house_price_idx, -- listings_scraped_desc_idx, listings_rooms_area_idx -> already full (de-partialed by 097) -- No is_active partial index remains anywhere in the public schema. -- -- This migration handles the ONE remaining duplicate that the original audit could -- not see, because it only emerged AS A SIDE-EFFECT of 097's de-partial: -- -- listings_geom_active_idx (050_search_optimization.sql:47) was originally -- GIST(geom) WHERE is_active = true. 097 stripped the predicate, so it is now -- GIST(geom) with no predicate — an EXACT duplicate of listings_geom_idx -- (002_core_tables.sql:57), the original full GIST on the same column. -- -- Prod evidence (2026-06-13, tradein-postgres): -- listings_geom_idx CREATE INDEX ... USING gist (geom) scan=131 7944 kB (KEEP, original) -- listings_geom_active_idx CREATE INDEX ... USING gist (geom) scan=83 3240 kB (DROP, duplicate) -- Both back no constraint (standalone). Dropping the duplicate frees ~3.2 MB and -- removes redundant write/VACUUM overhead. listings_geom_idx fully covers every -- spatial predicate the dropped index served (incl. the active-only queries, which -- simply add a WHERE is_active filter on top of the same GIST scan). -- -- NOTE on the original "is_active=100%" premise: that premise is now STALE. As of -- 2026-06-13 prod shows 19312 active / 39115 total listings (~49% active), so a -- WHERE is_active=true partial would NOT be pointless today. We are NOT re-adding -- the predicate here — listings_geom_idx (full) already covers the workload and a -- second geom index (partial or full) is pure redundancy. Flagged for awareness. -- -- Dependencies: 002_core_tables.sql (listings_geom_idx), 050_search_optimization.sql -- + 097_index_hygiene.sql (which de-partialed listings_geom_active_idx). -- Deploy order: any time after 097. Schema-only, low risk (tradein DB), short lock. -- DROP INDEX (non-CONCURRENTLY) is fine inside this transaction: brief -- ACCESS EXCLUSIVE on listings only, no CONCURRENTLY (which is illegal -- inside a txn block). -- -- Idempotency: DROP INDEX IF EXISTS. Safe to re-run. BEGIN; -- Exact duplicate of listings_geom_idx (002_core_tables.sql:57) after 097 removed its -- WHERE is_active=true predicate. Keep the original; drop this redundant twin. DROP INDEX IF EXISTS listings_geom_active_idx; COMMIT;