Kazde szukanie slowa w tytulach bylo sekwencyjnym skanem 3,46 mln wierszy. Blokowalo
to ranking over-attribution: metryka "ile scen ma te nazwe w tytule, ale NIE jest do
niej przypisanych" wymaga jednego skanu NA KANDYDATA, a kandydatow jest ~800. Proba
zostala ubita po 10 minutach.
GIN + gin_trgm_ops obsluguje LIKE, ILIKE i regexy, a pg_trgm sam normalizuje wielkosc
liter, wiec indeks na surowym title wystarcza. Efekt: 26 ms zamiast sekund na
zapytanie, ranking 800 kandydatow w 48 sekund zamiast godzin. Indeks 315 MB.
Zbudowany CONCURRENTLY w autocommit_block: zwykle CREATE INDEX trzymaloby lock
blokujacy zapisy na scenes przez cala budowe i zatrzymalo ingest.
Ranking od razu pokazuje dwie rozne rzeczy. Czyste smieci ("Pornhub" 105.9, "Monster"
92, "Pretty" 63, "Nice" 42) oraz SAME NAZWISKA (Devine, Starr, Dior, Cruz, West,
Knight, Johnson, James) - wpisy powstale z rozbicia imienia i nazwiska, ktore potem
lapia kazda scene z tym nazwiskiem, nalezaca do zupelnie innej osoby.
Usuniete przy okazji: "Pornhub" (108 scen, 0 z kanonu, wszystkie to "full video on
pornhub") i "Precious" (119 scen, 0 z kanonu, sam przymiotnik).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
46 lines
1.9 KiB
Python
46 lines
1.9 KiB
Python
"""indeks trigramowy na scenes.title
|
|
|
|
Revision ID: 0027_scenes_title_trgm
|
|
Revises: 0026_scene_performer_source
|
|
Create Date: 2026-07-27
|
|
|
|
Bez tego każde szukanie słowa w tytułach to sekwencyjny skan 3,46 mln wierszy. Blokowało
|
|
to ranking kandydatów do przeglądu over-attribution
|
|
(`scripts/review_performer_attributions.py`): metryka „ile scen ma tę nazwę w tytule, ale
|
|
NIE jest do niej przypisanych" wymaga jednego skanu NA KANDYDATA, a kandydatów jest ~800.
|
|
Przy skanie sekwencyjnym to godziny obciążania bazy — próba została ubita po 10 minutach.
|
|
|
|
GIN + `gin_trgm_ops` obsługuje `LIKE`, `ILIKE` i regexy (`~`, `~*`), a pg_trgm normalizuje
|
|
wielkość liter sam, więc indeks na surowym `title` wystarcza.
|
|
|
|
**CONCURRENTLY i `autocommit_block`**: zwykłe `CREATE INDEX` bierze lock blokujący zapisy
|
|
na `scenes` na cały czas budowy (kilka minut przy tej wielkości), czyli zatrzymałoby
|
|
ingest. `CONCURRENTLY` nie może biec w transakcji, a Alembic domyślnie owija migrację w
|
|
transakcję — stąd `autocommit_block()`.
|
|
|
|
Uwaga operacyjna: nieudane `CREATE INDEX CONCURRENTLY` zostawia indeks w stanie INVALID.
|
|
Sprawdzenie: `SELECT indexrelid::regclass FROM pg_index WHERE NOT indisvalid;` — taki
|
|
trzeba dropnąć ręcznie i powtórzyć.
|
|
"""
|
|
from collections.abc import Sequence
|
|
|
|
from alembic import op
|
|
|
|
revision: str = "0027_scenes_title_trgm"
|
|
down_revision: str | None = "0026_scene_performer_source"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
with op.get_context().autocommit_block():
|
|
op.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm")
|
|
op.execute(
|
|
"CREATE INDEX CONCURRENTLY IF NOT EXISTS ix_scenes_title_trgm "
|
|
"ON scenes USING gin (title gin_trgm_ops)"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
with op.get_context().autocommit_block():
|
|
op.execute("DROP INDEX CONCURRENTLY IF EXISTS ix_scenes_title_trgm")
|