perf(estimate): trigram expr index for same-building anchor Tier A (~94x) #1946

Merged
bot-backend merged 1 commit from perf/tradein-estimate-audit into main 2026-06-27 06:18:02 +00:00
Collaborator

Что

GIN trigram expression-индекс на lower(translate(address,'ёЁ','ее')) для same-building anchor Tier A эстиматора.

Почему (perf-аудит /estimate)

_fetch_anchor_comps Tier A запускается на КАЖДОЙ оценке (флаг estimate_same_building_anchor_enabled дефолт True, в проде не переопределён). Предикат оборачивает address в lower(translate(address,'ёЁ','ее')) для LIKE '%street%' И ~ regex по номеру дома — non-sargable. Существующий listings_address_trgm_idx на СЫРОМ address → не применим → Seq Scan по всем ~66.7k listings (167ms) на каждой оценке.

Доказательство (prod EXPLAIN, BEGIN/ROLLBACK, "Хохрякова 48")

До После
План Seq Scan (66714 rows removed) Bitmap Index Scan listings_addr_norm_trgm_idx
Время 167 ms 1.77 ms (~94x)
Buffers 15801 97

gin_trgm_ops обслуживает И LIKE, И regex. Result-identical (count/sum/min/max совпали — чистый access-path). Независимо перепроверил dry-run'ом: Bitmap Index Scan, 0.66ms.

Безопасность

  • ~8 MB (меньше существующего raw-address trgm 16 MB). Sub-second build, IF NOT EXISTS (идемпотентно), WHERE address IS NOT NULL (partial). pg_trgm на проде есть.
  • No code change — выражение индекса ТОЧНО совпадает с предикатом Tier A.
  • Существующий listings_address_trgm_idx (raw address) оставлен — нужен др. путям.

database-expert проверил весь estimate-hot-path: Tier W/H (geom+rooms BitmapAnd) и Tier S (house_id_fk) уже оптимальны — других индексов не нужно. Migration tradein-mvp/backend/data/sql/137.

## Что GIN trigram expression-индекс на `lower(translate(address,'ёЁ','ее'))` для same-building anchor Tier A эстиматора. ## Почему (perf-аудит /estimate) `_fetch_anchor_comps` Tier A запускается на **КАЖДОЙ** оценке (флаг `estimate_same_building_anchor_enabled` дефолт True, в проде не переопределён). Предикат оборачивает `address` в `lower(translate(address,'ёЁ','ее'))` для LIKE `'%street%'` И `~` regex по номеру дома — **non-sargable**. Существующий `listings_address_trgm_idx` на СЫРОМ address → не применим → **Seq Scan по всем ~66.7k listings (167ms)** на каждой оценке. ## Доказательство (prod EXPLAIN, BEGIN/ROLLBACK, "Хохрякова 48") | | До | После | |---|---|---| | План | Seq Scan (66714 rows removed) | **Bitmap Index Scan** `listings_addr_norm_trgm_idx` | | Время | **167 ms** | **1.77 ms** (~94x) | | Buffers | 15801 | 97 | `gin_trgm_ops` обслуживает И LIKE, И regex. Result-identical (count/sum/min/max совпали — чистый access-path). Независимо перепроверил dry-run'ом: Bitmap Index Scan, **0.66ms**. ## Безопасность - ~8 MB (меньше существующего raw-address trgm 16 MB). Sub-second build, IF NOT EXISTS (идемпотентно), `WHERE address IS NOT NULL` (partial). pg_trgm на проде есть. - **No code change** — выражение индекса ТОЧНО совпадает с предикатом Tier A. - Существующий `listings_address_trgm_idx` (raw address) оставлен — нужен др. путям. database-expert проверил весь estimate-hot-path: Tier W/H (geom+rooms BitmapAnd) и Tier S (house_id_fk) уже оптимальны — других индексов не нужно. Migration `tradein-mvp/backend/data/sql/137`.
bot-backend added 1 commit 2026-06-27 06:17:12 +00:00
perf(estimate): trigram expression index for same-building anchor Tier A (~94x)
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
8d5c1a888d
_fetch_anchor_comps Tier A runs on EVERY /estimate (flag
estimate_same_building_anchor_enabled defaults True, not overridden in prod).
Its address predicate wraps address in lower(translate(address,'ёЁ','ее')) for
both the LIKE '%street%' and the ~house-number regex — non-sargable, and the
existing listings_address_trgm_idx is on the RAW address, so the planner
seq-scanned all ~66.7k listings (167ms, 15801 buffers) every estimate.

Add a GIN trigram expression index on lower(translate(address,'ёЁ','ее'))
matching the predicate exactly (gin_trgm_ops serves both LIKE and the regex).
Prod EXPLAIN (BEGIN/ROLLBACK, "Хохрякова 48"): 167ms -> 1.77ms (~94x), buffers
15801 -> 97. Independently dry-run-verified: Bitmap Index Scan, 0.66ms.
Result-identical (pure access-path; count/sum/min/max unchanged). No code
change (expression matches the predicate). ~8MB, sub-second build.

Other estimate-path queries confirmed already optimal (Tier W/H geom+rooms
BitmapAnd, Tier S house_id_fk) — no other index warranted.

tradein-mvp/backend/data/sql/137 (correct tradein migrations path).
bot-backend merged commit 1fb33e20dd into main 2026-06-27 06:18:02 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1946
No description provided.