From 6d9110e064dbac39ae7543b20a8e5eadf40f59b2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:07:34 +0000 Subject: [PATCH] perf: add composite index for playlist thumbnails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `idx_playlist_video_sort` composite index on `(playlistId, sortOrder)` to `playlist_videos` table. - Optimizes `getAllPlaylistsWithStats` query by avoiding in-memory sort for thumbnail selection. - Add verification test in `test/integration/database_advanced.test.js`. - Add performance journal entry. ⚡ Bolt Optimization: ONE small performance improvement. --- .jules/bolt.md | 5 +++++ src/main/database.js | 6 ++++++ test/integration/database_advanced.test.js | 7 +++++++ 3 files changed, 18 insertions(+) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..72edf64 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,5 @@ +# Bolt's Journal + +## 2024-05-23 - Composite Index for Playlist Thumbnails +**Learning:** SQLite query optimizer needs explicit composite indexes for `WHERE x = ? ORDER BY y` clauses to avoid in-memory sorting, especially when used in correlated subqueries. +**Action:** Always check `ORDER BY` clauses in frequently run queries (like startup routines) and ensure covering indexes exist. diff --git a/src/main/database.js b/src/main/database.js index 03efb71..0d942b1 100644 --- a/src/main/database.js +++ b/src/main/database.js @@ -100,6 +100,7 @@ function initialize(app, customPath = null) { table.integer('sortOrder'); table.primary(['playlistId', 'videoId']); table.index('playlistId'); + table.index(['playlistId', 'sortOrder'], 'idx_playlist_video_sort'); }); } else { try { @@ -107,6 +108,11 @@ function initialize(app, customPath = null) { t.index('playlistId') ); } catch (e) {} + try { + await db.schema.alterTable('playlist_videos', (t) => + t.index(['playlistId', 'sortOrder'], 'idx_playlist_video_sort') + ); + } catch (e) {} } if (!(await db.schema.hasTable('artists'))) { diff --git a/test/integration/database_advanced.test.js b/test/integration/database_advanced.test.js index 320c895..630ccb8 100644 --- a/test/integration/database_advanced.test.js +++ b/test/integration/database_advanced.test.js @@ -123,4 +123,11 @@ describe('Advanced Database Logic', () => { expect(all.length).toBe(1); expect(all[0].name).toBe('Busy Artist'); }); + + test('should have composite index on playlist_videos', async () => { + const db = database.getDB(); + const indexes = await db.raw("PRAGMA index_list('playlist_videos')"); + const hasIndex = indexes.some(idx => idx.name === 'idx_playlist_video_sort'); + expect(hasIndex).toBe(true); + }); });