ix_scenes_title_created_id_desc zaczyna sie od tej samej kolumny, wiec obsluguje wszystko,
co obslugiwal stary indeks: lookupy `title_normalized = X` z resolvera i skan zakresu przy
sortowaniu po tytule. Trzymanie obu to 367 MB na dysku i jeden indeks wiecej do utrzymania
przy kazdym zapisie do scenes, a ingest pisze tam caly czas.
Sprawdzone na produkcji przez BEGIN; DROP INDEX; EXPLAIN ANALYZE; ROLLBACK, zeby zobaczyc
wybor planera bez starego indeksu, a potem jeszcze raz po samym dropie:
exact title lookup 1,76 ms -> 0,07 ms, Index Scan po nowym indeksie
OR studio + exact title ten sam ksztalt planu (BitmapOr), 3,7 ms
OR data + exact title Seq Scan przy szerokim oknie dat, ale to decyzja o release_date:
z enable_seqscan=off BitmapOr siega po nowy indeks
trgm ILIKE bez zmian, swoj indeks GIN
W wariancie z OR planer i tak siegal juz po nowy indeks, jeszcze zanim stary znikl.
Indeksy scenes: 3544 MB -> 3177 MB. Listy scen po dropie bez zmian (tytul 22-54 ms,
studio 38-73 ms na stronach 1-5).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
49 lines
1.9 KiB
Python
49 lines
1.9 KiB
Python
"""Indeks pod cale ORDER BY listy scen sortowanej po tytule.
|
|
|
|
`sort=title` konczy sie na `title_normalized ASC, created_at DESC, id DESC` (PK jako
|
|
ostateczny tie-break, zeby strony sie nie nakladaly). Stary `ix_scenes_title_normalized`
|
|
pokrywal tylko pierwszy czlon, wiec Postgres dokladal Incremental Sort, a ten przed
|
|
oddaniem PIERWSZEGO wiersza musi zebrac caly kubelek scen o tym samym tytule. Na stronie 1
|
|
glownego feedu ciagnal przez to 1084 wiersze zamiast 51 (709 ms zimno), a z filtrem taga
|
|
„blowjob" nie zmiescil sie w 90 s.
|
|
|
|
Pomiar na produkcji 2026-09-16, ten sam zestaw filtrow, po rozgrzewce:
|
|
strona 1 709 ms -> 12 ms (skan czyta 81 wpisow indeksu zamiast 3064)
|
|
strona 5 27 ms -> 9 ms
|
|
+ tag >90 s -> 1,1 s
|
|
|
|
Kierunki w indeksie musza byc dokladnie takie jak w ORDER BY, bo sort jest mieszany
|
|
(ASC, DESC, DESC) i inaczej skan nie przejdzie po kolei.
|
|
|
|
Ten indeks zaczyna sie od `title_normalized`, wiec obsluguje tez zwykle lookupy po tytule
|
|
(2,2 mln skanow), przez ktore stary `ix_scenes_title_normalized` staje sie zbedny. Usuwa go
|
|
migracja 0040, osobno, zeby dalo sie cofnac samo usuniecie.
|
|
|
|
CONCURRENTLY w autocommit_block, jak w 0035 i 0038. Nieudany CONCURRENTLY zostawia indeks
|
|
INVALID; wtedy DROP INDEX i ponownie.
|
|
|
|
Revision ID: 0039_scenes_title_created_id_idx
|
|
Revises: 0038_scenes_studio_effdate_idx
|
|
Create Date: 2026-09-16
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from alembic import op
|
|
|
|
revision = "0039_scenes_title_created_id_idx"
|
|
down_revision: str | None = "0038_scenes_studio_effdate_idx"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
with op.get_context().autocommit_block():
|
|
op.execute(
|
|
"CREATE INDEX CONCURRENTLY IF NOT EXISTS ix_scenes_title_created_id_desc "
|
|
"ON scenes (title_normalized, created_at DESC, id DESC)"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
with op.get_context().autocommit_block():
|
|
op.execute("DROP INDEX CONCURRENTLY IF EXISTS ix_scenes_title_created_id_desc")
|