Prosba uzytkownika (zgloszenie 17376139). Backend mial juz parametr `min_quality_p`, ale w praktyce byl NIEUZYWALNY i to zajelo wiekszosc pracy. Wydajnosc, mierzona na produkcji przez EXPLAIN ANALYZE, prog 1080p: EXISTS na playback_sources (stan zastany) 32 s 3 556 612 odwiedzonych scen + indeks funkcyjny per-scena 24 s JOIN z DISTINCT po jakosci 1,1 s W IZOLACJI ten sam JOIN + reszta filtrow feedu 52 s planer wraca do skanu po dacie kolumna scenes.max_quality_p (0029) 2,0-2,6 s + indeksy czesciowe pod progi (0030) 0,09-0,11 s Wniosek, ktory kosztowal najwiecej: ksztaltem zapytania sie tego NIE dalo zalatwic. Koszt to LICZBA odwiedzonych scen, nie pojedynczy test, a przy `ORDER BY created_at DESC LIMIT 24` planer i tak wracal do przechodzenia scen po dacie, gdy tylko doszly pozostale filtry (bramka wertykalow, heurystyka szkieletow, prog dlugosci). Stad denormalizacja + indeksy czesciowe z predykatem progu, ktore daja gotowe sortowanie. Semantyka SUROWA, swiadomie: `quality` zapisujemy oportunistycznie, zna ja 6,5% scen (210 302 z 3 236 368), najlepsze zrodlo ma 26% pokrycia. Wariant lagodny, przepuszczajacy sceny o nieznanej jakosci, odrzucony po zmierzeniu: odsiewalby 88 647 z 3,2 mln, czyli nie realizowalby intencji "nie chce ogladac ziemniaka". Filtr pokazuje wiec tylko jakosc POTWIERDZONA, a UI mowi to wprost podpisem pod przelacznikiem, bo inaczej gwaltowny spadek liczby wynikow wyglada na zepsuta aplikacje. Warianty tekstowe 4K/UHD usuniete z warunku: 0 wystapien na 238 452 zywe zrodla, a `OR ilike` blokowal uzycie indeksu. Odswiezanie w taxonomy_counts (co 3h), z czyszczeniem do NULL gdy scena traci zrodlo z jakoscia. Backfill: 210 302 sceny w 2m56s. Zweryfikowane na emulatorze: sekcja MIN QUALITY renderuje sie z podpisem ostrzegawczym. Lista wyszla pusta, ale to build debugowy dostajacy 403 (podpis debug spoza allowlisty), nie blad filtra: ten sam URL z poprawnym podpisem oddaje 50 wynikow w 0,12 s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
"""Indeksy czesciowe pod progi filtra jakosci (720/1080/2160)
|
|
|
|
Dlaczego osobne indeksy na prog, a nie jeden na (max_quality_p, created_at):
|
|
tamten nie da sie uzyc do `ORDER BY created_at DESC LIMIT n`, bo wynik nie jest
|
|
posortowany po created_at w obrebie ZAKRESU wartosci max_quality_p. Planer go
|
|
ignorowal i wracal do przejscia `scenes` po dacie z filtrem.
|
|
|
|
Indeks czesciowy z predykatem `max_quality_p >= N`, posortowany po created_at DESC,
|
|
jest dla progu N dokladnie tym, czego zapytanie potrzebuje: Postgres uzywa go, gdy
|
|
warunek zapytania implikuje predykat indeksu. Zmierzone na produkcji 2026-08-18:
|
|
|
|
0029 (sama kolumna) 2,0-2,6 s planer szedl ix_scenes_created_at_desc
|
|
0030 (te indeksy) 0,09-0,11 s Index Scan using ix_scenes_created_q1080
|
|
|
|
Progi sa ZWIAZANE Z UI: `QUALITY_OPTIONS` w mobile/src/screens/ScenesFilterModal.tsx
|
|
oferuje dokladnie 720/1080/2160. Inna wartosc w `?min_quality_p=` nadal dziala, tylko
|
|
wolniej (fallback do skanu po dacie). Dodajac opcje w UI, dodaj tu indeks.
|
|
|
|
Rozmiary sa pomijalne (4,3 MB / 2,7 MB / 0,3 MB), bo jakosc zna tylko 6,5% katalogu.
|
|
|
|
Revision ID: 0030_scenes_quality_idx
|
|
Revises: 0029_scenes_max_quality
|
|
Create Date: 2026-08-18
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "0030_scenes_quality_idx"
|
|
down_revision: str | None = "0029_scenes_max_quality"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
_THRESHOLDS = (720, 1080, 2160)
|
|
|
|
|
|
def upgrade() -> None:
|
|
for q in _THRESHOLDS:
|
|
op.create_index(
|
|
f"ix_scenes_created_q{q}",
|
|
"scenes",
|
|
[sa.text("created_at DESC")],
|
|
postgresql_where=sa.text(f"max_quality_p >= {q}"),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
for q in _THRESHOLDS:
|
|
op.drop_index(f"ix_scenes_created_q{q}", table_name="scenes")
|