goon/alembic/versions/20260922_0046_scenes_title_stats.py
goon-foss 45ee7a81e1
Some checks are pending
Backend tests / test (push) Waiting to run
fix(api): szybkie szukanie po tytule dla popularnych i krotkich fraz
Planer szacowal kazda fraze na 427 trafien (histogram 100 probek, dolny limit), wiec
zawsze szedl indeksem trigramow i sortowal wszystkie trafienia: "vo" 44 s (dwie
litery nie maja trigramu, indeks oddaje 4,3 mln wierszy), "mis" 6,5 s, "free" 1,9 s
(GOON-73/75).

- 0046: histogram title_normalized 1000 probek, szacunki bliskie prawdy.
- list_scenes: przy q i sorcie po dacie najpierw przejscie po indeksie sortu z
  limitem 300 ms (bez bitmap, w SAVEPOINT wycofywanym zawsze), gdy probka tytulow
  z pg_stats mowi, ze wystarczy przejsc do 30 tys. scen; inaczej zwykly plan.
  Frazy bez trigramu zawsze przejsciem (limit 3 s, potem pusto).

115 prawdziwych wyszukiwan z logow: wyniki identyczne, najgorszy 44 s -> 0,8 s,
srednie frazy dotykaja 3-7x mniej stron ("bad" 122 tys. -> 16 tys.).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 12:00:11 +02:00

36 lines
1.4 KiB
Python

"""Wiekszy histogram statystyk dla scenes.title_normalized (szukanie po tytule).
Postgres szacuje `ILIKE '%fraza%'` z histogramu kolumny. Przy domyslnych 100 probkach
popularne frazy nie trafialy w zadna i szacunek spadal na dolny limit 0,01% (427 scen),
wiec planista zawsze szedl przez indeks trigramow i potem sortowal wszystkie trafienia:
"vo" 44 s (dwie litery nie maja trigramu, indeks oddaje 4,3 mln wierszy), "mis" 6,5 s,
"free" 1,9 s (Sentry GOON-73/75, 2026-09-22). Z 1000 probkami szacunki sa bliskie
prawdy i dla popularnych fraz wygrywa przejscie po ix_scenes_created_at_desc do 51.
trafienia: 9 ms, 15 ms, 60 ms. Rzadkie frazy dalej ida przez trigramy.
ANALYZE samej kolumny czyta probke 300 tys. wierszy, kilkanascie sekund.
Revision ID: 0046_scenes_title_stats
Revises: 0045_autovacuum_big_tables
Create Date: 2026-09-22
"""
from __future__ import annotations
from alembic import op
revision = "0046_scenes_title_stats"
down_revision: str | None = "0045_autovacuum_big_tables"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.execute("SET LOCAL lock_timeout = '5s'")
op.execute("ALTER TABLE scenes ALTER COLUMN title_normalized SET STATISTICS 1000")
op.execute("ANALYZE scenes (title_normalized)")
def downgrade() -> None:
op.execute("SET LOCAL lock_timeout = '5s'")
op.execute("ALTER TABLE scenes ALTER COLUMN title_normalized SET STATISTICS -1")
op.execute("ANALYZE scenes (title_normalized)")