fix(sql): restore partial predicate on 5 listings indexes (#1398)
All checks were successful
CI / changes (push) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
All checks were successful
CI / changes (push) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
097_index_hygiene.sql de-partialized 5 listings indexes on the false premise that is_active=100% true. 104_index_hygiene_geom_dedup.sql acknowledged the premise is stale (49% active on prod, 2026-06-13) but only cleaned up the redundant geom duplicate, leaving 3 composite indexes full. Restore WHERE is_active=true on the composite hot-path indexes: - listings_active_filter_idx (rooms, price_rub, area_m2, scraped_at DESC) - listings_house_price_idx (house_id_fk, price_rub) - listings_rooms_area_idx (rooms, area_m2) Excluded: listings_geom_active_idx (dropped by 104, listings_geom_idx covers it), listings_scraped_desc_idx (not in issue #1398 suggested fix scope). CONCURRENTLY not used — migration runner wraps in BEGIN/COMMIT (see 117 note).
This commit is contained in:
parent
ba83c36bf4
commit
403020ad56
1 changed files with 68 additions and 0 deletions
|
|
@ -0,0 +1,68 @@
|
|||
-- 120_restore_partial_active_indexes.sql
|
||||
-- Fixes #1398: restore WHERE is_active = true predicate on 3 composite listings indexes
|
||||
-- that were de-partialized by 097_index_hygiene.sql on the false premise that
|
||||
-- is_active is 100% true. 104_index_hygiene_geom_dedup.sql explicitly acknowledges the
|
||||
-- premise is stale (prod 2026-06-13: 19312 active / 39115 total, ~49% active), but
|
||||
-- only dropped the redundant geom duplicate -- the composite indexes were left full.
|
||||
--
|
||||
-- Indexes restored with WHERE is_active = true predicate:
|
||||
-- 1. listings_active_filter_idx (rooms, price_rub, area_m2, scraped_at DESC)
|
||||
-- 2. listings_house_price_idx (house_id_fk, price_rub)
|
||||
-- 3. listings_rooms_area_idx (rooms, area_m2)
|
||||
--
|
||||
-- These indexes directly back the estimator hot-path (estimator.py _COMMON_WHERE:
|
||||
-- AND rooms = :rooms AND area_m2 BETWEEN ... AND is_active = true AND price_rub > 0)
|
||||
-- and asking_to_sold_ratio.py, which always filters is_active = true.
|
||||
-- Restoring the predicate excludes ~51% inactive rows from the index, making it
|
||||
-- roughly half the size and allowing index-only scans on active-only queries.
|
||||
--
|
||||
-- Excluded from restore:
|
||||
-- listings_geom_active_idx -- dropped by 104 as exact dup of listings_geom_idx
|
||||
-- (keep listings_geom_idx as the single full GIST)
|
||||
-- listings_scraped_desc_idx -- simple recency sort not in hot-path composite filters;
|
||||
-- issue #1398 suggested fix does not include it
|
||||
--
|
||||
-- Note on CONCURRENTLY:
|
||||
-- NOT used here. The deploy migration runner wraps each file in an explicit
|
||||
-- transaction (BEGIN/COMMIT). CREATE INDEX CONCURRENTLY cannot run inside a
|
||||
-- transaction block. At ~40k rows the ACCESS EXCLUSIVE lock is sub-second.
|
||||
-- See migration 117_listings_last_seen_deactivate_index.sql for the same rationale.
|
||||
--
|
||||
-- Idempotency:
|
||||
-- DROP INDEX IF EXISTS + CREATE INDEX IF NOT EXISTS -- safe to re-run.
|
||||
--
|
||||
-- Dependencies: 002_core_tables.sql, 050_search_optimization.sql,
|
||||
-- 097_index_hygiene.sql (de-partialized these indexes),
|
||||
-- 104_index_hygiene_geom_dedup.sql (acknowledges stale premise)
|
||||
-- Deploy order: standalone, apply any time after 097 + 104.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 1. listings_active_filter_idx
|
||||
-- Original (050_search_optimization.sql:52):
|
||||
-- ON listings (rooms, price_rub, area_m2, scraped_at DESC) WHERE is_active = true
|
||||
-- 097 stripped the predicate. Restoring it.
|
||||
DROP INDEX IF EXISTS listings_active_filter_idx;
|
||||
CREATE INDEX IF NOT EXISTS listings_active_filter_idx
|
||||
ON listings (rooms, price_rub, area_m2, scraped_at DESC)
|
||||
WHERE is_active = true;
|
||||
|
||||
-- 2. listings_house_price_idx
|
||||
-- Original (050_search_optimization.sql:57):
|
||||
-- ON listings (house_id_fk, price_rub) WHERE is_active = true
|
||||
-- 097 stripped the predicate. Restoring it.
|
||||
DROP INDEX IF EXISTS listings_house_price_idx;
|
||||
CREATE INDEX IF NOT EXISTS listings_house_price_idx
|
||||
ON listings (house_id_fk, price_rub)
|
||||
WHERE is_active = true;
|
||||
|
||||
-- 3. listings_rooms_area_idx
|
||||
-- Original (002_core_tables.sql:58):
|
||||
-- ON listings (rooms, area_m2) WHERE is_active = true
|
||||
-- 097 stripped the predicate. Restoring it.
|
||||
DROP INDEX IF EXISTS listings_rooms_area_idx;
|
||||
CREATE INDEX IF NOT EXISTS listings_rooms_area_idx
|
||||
ON listings (rooms, area_m2)
|
||||
WHERE is_active = true;
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Reference in a new issue