The filtered scene-list endpoints (default feed sends min_duration_sec=60, plus has_playback / tag / q filters) took ~4.5s — and an idle server. Profiling showed the entire cost was the bounded COUNT subquery over the EXISTS filters: Postgres would not reliably early-terminate at the cap under psycopg bound params, scanning the whole matching set (~858k for has_playback). Counting over the PK and using a literal LIMIT helped some cases but the plan stayed unstable. Fix: stop computing an exact count for filtered lists entirely. The mobile client paginates by has_more (per_page+1 fetch), never by total — total is only the "N+" UI counter. Derive total as a lower bound from the page + has_more after the fetch. This removes the count query from every filtered request. Result (end-to-end, authenticated): default feed 4.5s -> ~0.1s, has_playback 4.4s -> ~0.1s, q/studio/normal-tag filters all <0.3s. Also added index scene_tags(tag_id, scene_id) (PK led with scene_id, so tag->scenes did a seq scan). Remaining: a single enormous tag (e.g. "anal", ~163k scenes) ordered by recency still gathers-all-then-sorts in the fetch (~5s); normal tags are <0.5s. Tracked in #22 for a denormalized recency-ordered approach. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| init | ||
| versions | ||
| env.py | ||
| script.py.mako | ||