perf(database): add composite indexes for hot ORDER BY paths

The existing single-column indexes force a sort step for the most common
list queries. These three composite indexes let SQLite scan in index
order and skip the sort entirely:

- recently_viewed(playlist_id, viewed_at DESC):
  getRecentItems(): WHERE playlist_id = ? ORDER BY viewed_at DESC LIMIT 100
- favorites(playlist_id, position, added_at DESC):
  getFavorites/getGlobalFavorites/getAllGlobalFavorites():
  WHERE playlist_id = ? ORDER BY position ASC, added_at DESC
- playback_positions(playlist_id, updated_at DESC):
  getRecentPlaybackPositions(): WHERE playlist_id = ? ORDER BY updated_at DESC LIMIT 20

CREATE INDEX IF NOT EXISTS so existing DBs pick up the new indexes on
next startup with no migration required. Mirrored in the Drizzle schema
using sql\`col DESC\` so the ORM stays the source of truth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 3d6901072049
This commit is contained in:
4grayandClaude Opus 4.7 committed 2026-05-01 21:11:44 +02:00
1 parent eedfc498e7
commit 9ecf4d44d3
2 files changed
+15

No files matched your search

@@ -150,6 +150,8 @@ const CREATE_TABLE_STATEMENTS = [
`CREATE UNIQUE INDEX IF NOT EXISTS recently_viewed_content_playlist_unique ON recently_viewed(content_id, playlist_id)`,
`CREATE INDEX IF NOT EXISTS recently_viewed_playlist_idx ON recently_viewed(playlist_id)`,
`CREATE INDEX IF NOT EXISTS recently_viewed_viewed_at_idx ON recently_viewed(viewed_at)`,
`CREATE INDEX IF NOT EXISTS recently_viewed_playlist_viewed_idx ON recently_viewed(playlist_id, viewed_at DESC)`,
`CREATE INDEX IF NOT EXISTS favorites_playlist_position_idx ON favorites(playlist_id, position, added_at DESC)`,
// EPG tables
`CREATE TABLE IF NOT EXISTS epg_channels (
id TEXT PRIMARY KEY,
@@ -220,6 +222,7 @@ const CREATE_TABLE_STATEMENTS = [
`CREATE INDEX IF NOT EXISTS playback_positions_playlist_idx ON playback_positions(playlist_id)`,
`CREATE INDEX IF NOT EXISTS playback_positions_series_idx ON playback_positions(series_xtream_id)`,
`CREATE INDEX IF NOT EXISTS playback_positions_updated_idx ON playback_positions(updated_at)`,
`CREATE INDEX IF NOT EXISTS playback_positions_playlist_updated_idx ON playback_positions(playlist_id, updated_at DESC)`,
// Downloads table
`CREATE TABLE IF NOT EXISTS downloads (
id INTEGER PRIMARY KEY AUTOINCREMENT,
+12
View File
@@ -129,6 +129,10 @@ export const recentlyViewed = sqliteTable(
).on(table.contentId, table.playlistId),
playlistIdx: index('recently_viewed_playlist_idx').on(table.playlistId),
viewedAtIdx: index('recently_viewed_viewed_at_idx').on(table.viewedAt),
playlistViewedIdx: index('recently_viewed_playlist_viewed_idx').on(
table.playlistId,
sql`${table.viewedAt} DESC`
),
})
);
@@ -153,6 +157,11 @@ export const favorites = sqliteTable(
).on(table.contentId, table.playlistId),
playlistIdx: index('favorites_playlist_idx').on(table.playlistId),
contentIdx: index('favorites_content_idx').on(table.contentId),
playlistPositionIdx: index('favorites_playlist_position_idx').on(
table.playlistId,
table.position,
sql`${table.addedAt} DESC`
),
})
);
@@ -241,6 +250,9 @@ export const playbackPositions = sqliteTable(
table.seriesXtreamId
),
updatedIdx: index('playback_positions_updated_idx').on(table.updatedAt),
playlistUpdatedIdx: index(
'playback_positions_playlist_updated_idx'
).on(table.playlistId, sql`${table.updatedAt} DESC`),
})
);