gendesign/data/sql/176_objective_lots_physflat_covering_idx.sql
bot-backend 94d01ed066
Some checks failed
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 10m23s
Deploy / build-worker (push) Successful in 11m34s
Deploy / deploy (push) Failing after 8m8s
perf(objective_lots): inline-pushdown competitors._SOLD_COUNT_SQL + covering physflat index (#1953) (#2054)
2026-06-28 14:07:49 +00:00

76 lines
4.4 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Контекст: perf-батч после prod-EXPLAIN-охоты (follow-up эпика #1953, пункты #2/#6/#5).
--
-- #2/#6 — делаем physflat-индекс ПОКРЫВАЮЩИМ, дропаем старый partial.
-- EKB-wide дефолт market_metrics._STOCK_SQL (has_district=F/has_obj_ids=F) и
-- зеркальный _SALES_WINDOW_SQL дедуплицируют objective_lots до последнего снапшота
-- на физлот через
-- SELECT DISTINCT ON (project_name, corpus_name, section, floor, lot_number) …
-- ORDER BY …, snapshot_date DESC, id DESC
-- по квартирам (premise_kind='квартира'). Partial-индекс миграции 173
-- (objective_lots_physflat_latest_idx) совпадал с ключом DISTINCT ON, НО НЕ нёс
-- проецируемых колонок → Index-Only невозможен. Планировщик брал Parallel Seq Scan
-- + external merge Sort всех 1.75M квартир-строк (прод-EXPLAIN 2026-06-28:
-- ~5177 ms, temp-spill ~140 MB на трёх воркерах) вместо чтения из индекса.
--
-- Покрывающий индекс добавляет INCLUDE с колонками, которые проецируют/агрегируют
-- ОБА запроса ПОСЛЕ DISTINCT ON:
-- _STOCK_SQL: rooms_int, area_pd, sales_start_date + sold_now-предикат
-- (is_sold, contract_date, status)
-- _SALES_WINDOW_SQL: rooms_int, area_pd, contract_date, class
-- Объединение INCLUDE = {rooms_int, area_pd, sales_start_date, is_sold,
-- contract_date, status, class}. Ключ (physflat + snapshot_date DESC, id DESC) и
-- partial-WHERE (premise_kind='квартира') не меняются → тот же DISTINCT ON, но
-- теперь Index-Only Scan + Unique БЕЗ Sort.
-- Прод DRY-RUN (BEGIN; CREATE covering; EXPLAIN ANALYZE EKB-wide _STOCK_SQL;
-- ROLLBACK): Index Only Scan using objective_lots_physflat_covering_idx + Unique,
-- внешней сортировки НЕТ, Execution ~1642 ms (vs ~5177 ms). Размер ~252 MB.
--
-- price_per_m2_rub в INCLUDE НЕ кладём: его проецируют только analyze-inline
-- запросы (concepts._OBJECTIVE_MEDIAN_SQL, parcels district/geo-median), а они
-- НЕ фильтруют premise_kind='квартира' → partial-индекс к ним и так неприменим
-- (как и старый 173). Их обслуживают idx_objective_lots_pname_pricing / district-
-- /geo-пути — не регрессируют (никогда не использовали partial physflat-индекс).
--
-- Старый partial objective_lots_physflat_latest_idx ДРОПАЕМ: покрывающий индекс
-- его полностью замещает (тот же ключ + WHERE) и обслуживает все DISTINCT ON-
-- потребители (#1959 inline _STOCK/_SALES, competitors._SOLD_COUNT_SQL inline,
-- analyze-inline по квартирам). Держать оба — лишний write-amp на bulk objective-
-- scrape.
--
-- Порядок: CREATE covering → DROP old (covering уже на месте, ни одного окна без
-- индекса под DISTINCT ON). Idempotent (IF NOT EXISTS / IF EXISTS), BEGIN/COMMIT.
--
-- #5 — статистика objective_lots устаревала (last_analyze был 2026-05-11, planner
-- оценивал ~880 строк при реальных ~603k → плохие планы). ANALYZE в конце tx
-- (выполняется в транзакции штатно) освежает оценки под новый индекс.
--
-- ⚠ Деплой ВНЕ недельного окна objective-scrape: миграция дропает+создаёт ~252 MB
-- индекс на 1.75M строк (кратковременный SHARE-lock на objective_lots).
BEGIN;
CREATE INDEX IF NOT EXISTS objective_lots_physflat_covering_idx
ON objective_lots (
project_name,
corpus_name,
section,
floor,
lot_number,
snapshot_date DESC,
id DESC
)
INCLUDE (
rooms_int,
area_pd,
sales_start_date,
is_sold,
contract_date,
status,
class
)
WHERE premise_kind = 'квартира';
DROP INDEX IF EXISTS objective_lots_physflat_latest_idx;
ANALYZE objective_lots;
COMMIT;