Fix Following page: replace 9-subquery-per-channel stats with 2 CTEs + indexes

The old _CHANNEL_STATS_SELECT ran 9 correlated subqueries for each
channel row. With 1266 channels that was ~11000 sub-executions per
GET /channels request, causing multi-second (or timeout) delays.

New approach: 2 CTEs (vinfo for counts/sums, nc for new_count) each do
a single aggregated pass over all followed-channel videos, joined back
to channels. Only 2 correlated LIMIT-1 subqueries remain for
latest_video_id/title (fast with the new index).

Also adds 4 indexes on startup (IF NOT EXISTS — safe to deploy):
- videos(channel_id, published_at DESC)  — latest video lookups
- videos(channel_id, indexed_at)         — new_count filter
- user_videos(video_id, user_id)         — watch/download aggregation
- user_channels(user_id, status)         — followed channel filter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mattias Tall
2026-05-26 16:04:41 +02:00
parent 1cd8645957
commit 74e9a52096
2 changed files with 54 additions and 25 deletions

View File

@@ -89,6 +89,18 @@ def init_db():
_add_column_if_missing(raw_conn, "videos", "like_count", "INTEGER")
_add_column_if_missing(raw_conn, "videos", "dislike_count", "INTEGER")
raw_conn.commit()
# Indexes that make the channel-stats CTE query fast with many channels
for idx_sql in [
"CREATE INDEX IF NOT EXISTS idx_videos_channel_published ON videos(channel_id, published_at DESC)",
"CREATE INDEX IF NOT EXISTS idx_videos_channel_indexed ON videos(channel_id, indexed_at)",
"CREATE INDEX IF NOT EXISTS idx_user_videos_video_user ON user_videos(video_id, user_id)",
"CREATE INDEX IF NOT EXISTS idx_user_channels_user_status ON user_channels(user_id, status)",
]:
try:
raw_conn.execute(idx_sql)
except Exception:
pass
raw_conn.commit()
# executescript handles multi-statement SQL including trigger BEGIN...END blocks
raw_conn.executescript(FTS_SETUP_SQL)
finally: