gendesign/data/sql/174_domrf_kn_flats_obj_snapshot_idx.sql
Light1YT 8aec625134
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Successful in 1m2s
CI / openapi-codegen-check (pull_request) Successful in 1m56s
CI / backend-tests (pull_request) Successful in 14m7s
fix(audit): index for flats_latest, coerce max_height_m, hide empty reg-date (#1953)
Three #1953 audit follow-ups:

- perf: add migration 174 — composite index idx_kn_flats_obj_snap on
  domrf_kn_flats (obj_id, snapshot_date DESC). Serves the #1956 flats_latest
  CTE in best_layouts.py (DISTINCT ON (obj_id) ORDER BY obj_id, snapshot_date
  DESC + self-join on (obj_id, snapshot_date)); previously only (obj_id)
  existed so Postgres sorted per object. Prod: 789 569 rows, idx ~5.7 MB,
  dry-run instant. Idempotent, self-wrapped BEGIN/COMMIT.

- frontend: route every max_height_m read through coerceFloat (same string-bug
  class as max_far #1962). max_height_m is NUMERIC → arrives as a string on the
  wire; ptica-adapt.ts read it raw at 4 sites and relied on formatInt/Math.round
  coercion. Widen the type in nspd.ts and fix the stale "real number" comment in
  nspd-regulation.ts.

- frontend: hide the «Дата регистрации» EGRN row entirely when
  registration_date is null (~97% of parcels) instead of rendering a bare «—».
2026-06-28 03:19:18 +05:00

35 lines
1.5 KiB
PL/PgSQL

-- 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;