-- 174_domrf_kn_flats_obj_snapshot_idx.sql
--
-- Composite index on domrf_kn_flats (obj_id, snapshot_date DESC).
--
-- Serves the `flats_latest` CTE in best_layouts.py (#1956 supply batch query,
-- backend/app/services/site_finder/best_layouts.py:_SUPPLY_BATCH_SQL):
--
--     flats_latest AS (
--         SELECT DISTINCT ON (f.obj_id) f.obj_id, f.snapshot_date
--         FROM domrf_kn_flats f
--         JOIN nearby n ON n.obj_id = f.obj_id
--         ORDER BY f.obj_id, f.snapshot_date DESC, f.id DESC
--     )
--     ... JOIN domrf_kn_flats f ON f.obj_id = fl.obj_id
--                              AND f.snapshot_date = fl.snapshot_date
--
-- domrf_kn_flats is a per-object time-series (UNIQUE (obj_id, snapshot_date));
-- the DISTINCT ON + ORDER BY obj_id, snapshot_date DESC picks each object's
-- newest snapshot, and the self-join re-fetches that snapshot's rows by
-- (obj_id, snapshot_date). The only existing index covering obj_id is
-- idx_kn_flats_obj (obj_id) alone, so Postgres sorts per object on
-- snapshot_date instead of reading it pre-ordered. A composite
-- (obj_id, snapshot_date DESC) lets DISTINCT ON walk the index and lets the
-- join probe by (obj_id, snapshot_date) directly.
--
-- Prod (2026-06-28): domrf_kn_flats = 789 569 rows; no (obj_id, snapshot_date)
-- index present. DRY-RUN (BEGIN; CREATE INDEX; ROLLBACK) succeeded — index size
-- ~5.7 MB, builds instantly. Idempotent: IF NOT EXISTS.

BEGIN;

CREATE INDEX IF NOT EXISTS idx_kn_flats_obj_snap
    ON domrf_kn_flats (obj_id, snapshot_date DESC);

COMMIT;
