feat(obj-2): mapping backfill via pre-materialized temp tables (migration 117) #327
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#327
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/117-obj2-mapping-backfill-fast"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fix coverage regression в Site Finder после deploy OBJ-3 PR #324.
Problem
User report: на участке
66:41:0204016:10velocity показывает 0, «срок продажи 1092 мес» overflow. Coverage = 3/20 ЖК (15%) для competitors блока. 17 ЖК Железнодорожного района безobjective_complex_mappingзапись → LEFT JOIN отдаёт NULL → aggregates broken.Live verification (POST /parcels/.../analyze)
3 ЖК с правильными данными (acceptance criterion соблюдается):
Цены ∈ [110-220k] ✅. Но 17/20 без данных.
Fix
Migration 117 делает фактический mapping INSERT который был skip'нут в hotfix #326:
_u_domrf(~1056 rows)_u_obj(~178 rows)name_sim*0.6 + dev_match*0.25 + district_match*0.15ON CONFLICT DO NOTHINGmv_layout_velocityCONCURRENTLYWhy fast
Original 116 CTE recomputed unmapped lists для каждой строки → 89M cost timeout. Pre-materialized temp tables вычисляются один раз, далее GIST trgm index делает per-row LIMIT 1 dirt-cheap → estimated <30s runtime.
Expected outcome
objective_complex_mappingcount: 142 → ~200 (+50-80)Acceptance
После deploy + REFRESH MV:
Part of issue #307 OBJ-2 (deferred INSERT from migration 116 hotfix #326).
Deep Code Review — PR #327
Verdict: APPROVE
Single-file SQL migration, +91/-0. Pre-materialization strategy is sound and actually addresses the 89M-cost timeout (not cosmetic).
Cardinality / cost analysis
The original 116 timeout came from per-row recomputation of
NOT EXISTS (mapping lookup)insideCROSS JOIN LATERALover the fulldomrf_kn_objects × objective_lotsproduct. Three independent optimizations stack here:_u_domrf(~1056 rows) —NOT EXISTSevaluated once during materialization._u_obj(~178 distinct rows) —NOT IN (... mapping ...)evaluated once, plusDISTINCTcollapses duplicate (project_name, developer, district) tuples fromobjective_lots._u_objonly (~178 rows) per outer_u_domrfrow → 1056 × 178 = 188k similarity() calls total. Each is μs-cheap → well under 30s without any index help.Note on GIST trgm index claim
PR description says LATERAL "leverages GIST trgm index from migration 116". Strictly that index is on
objective_lots.project_name, not on the temp table_u_obj— temp tables don't inherit source indexes. The real performance win is the cardinality collapse, not the index. The migration is still fast (188k similarity calls is trivial), so this is a documentation nit, not a correctness issue.Correctness checklist
composite >= 0.75matches #323 ✓ROW_NUMBER() OVER (PARTITION BY obj_id ORDER BY composite DESC, name_sim DESC)with tiebreaker — deterministic ✓ON CONFLICT (objective_complex_name, objective_group) DO NOTHING— matches verified UNIQUE constraint, idempotent on re-apply ✓COALESCEfor NULL dev_name / district_name ✓dev_matchguards againstdev_norm <> ''(avoids false-positive when both sides normalize to empty) ✓Transaction boundary
BEGIN; ... CREATE TEMP TABLE ... ON COMMIT DROP ... INSERT ... COMMIT;✓REFRESH MATERIALIZED VIEW CONCURRENTLY mv_layout_velocity;outside BEGIN/COMMIT ✓ — required because CONCURRENTLY cannot run in an explicit transaction block.mv_layout_velocity_pkunique index exists (verified in #323).Idempotency / retry safety
ON COMMIT DROP— auto-cleanup ✓ON CONFLICT DO NOTHING— partial reruns safe ✓Minor nit (low severity, not blocking)
Line 17, 31:
regexp_replace(lower(...), '[^а-яa-z0-9]', '', 'g')— the Cyrillic char classа-я(U+0430-U+044F) does not includeё(U+0451). A developer name containingёwill have that letter stripped. Comparison stays symmetric (both sides apply same regex), so dev_match still works correctly — just a known minor coverage edge for any developer withёin the name. No fix needed for this PR.Risk
DELETE FROM objective_complex_mapping WHERE match_method='multi_feature_v1' AND note LIKE '%117_fast%'if rollback needed.Merging.