perf(library): resolve album and genre file paths in one query
"Play this artist" awaited `GetAlbumTracks` inside a for loop — 13 sequential round trips for a 12-album artist — and every one of the four sites doing that asked for whole track rows to read `FilePath` off them. Five genres cost 6 MB across the IPC. `GetFilePathsByAlbums(ids, libraryID)` and `GetFilePathsByGenres(names, libraryID)` answer once and carry only the paths. Measured at 50 000 tracks: an artist 13 calls / 74.2 kB -> 2 / 19.2 kB, twenty albums 20 / 117.5 kB / 7.8 ms -> 1 / 26.0 kB / 1.7 ms, five genres 5 / 6 014 kB / 213 ms -> 1 / 1 291 kB / 32.6 ms, with the returned path lists identical. They return the paths grouped by album id or genre name rather than flattened, because the caller owns the order — an album list is sorted by name, not by id, and a flattened result would silently reorder a queue — and because the album drag cache stores them per album. A libraryID of 0 means "every library", matching an unset filter.
This commit is contained in:
@@ -295,3 +295,26 @@ LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
||||
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||
WHERE rgr.release_group_id = ? AND af.library_id = ?
|
||||
ORDER BY rgr.disc_number, rgr.track_number;
|
||||
|
||||
-- "Play this artist" and "play these albums" wanted file paths and asked
|
||||
-- for whole track rows to get them, one round trip per album (perf.m2).
|
||||
-- These answer the same question in one query and carry only what the
|
||||
-- caller uses; the release group id comes back so the caller can keep
|
||||
-- its own album ordering.
|
||||
|
||||
-- name: GetFilePathsByReleaseGroups :many
|
||||
SELECT rgr.release_group_id, af.file_path
|
||||
FROM release_group_recordings rgr
|
||||
JOIN recordings r ON rgr.recording_id = r.id
|
||||
JOIN audio_files af ON af.recording_id = r.id
|
||||
WHERE rgr.release_group_id IN (sqlc.slice('release_group_ids'))
|
||||
ORDER BY rgr.disc_number, rgr.track_number;
|
||||
|
||||
-- name: GetFilePathsByReleaseGroupsByLibrary :many
|
||||
SELECT rgr.release_group_id, af.file_path
|
||||
FROM release_group_recordings rgr
|
||||
JOIN recordings r ON rgr.recording_id = r.id
|
||||
JOIN audio_files af ON af.recording_id = r.id
|
||||
WHERE rgr.release_group_id IN (sqlc.slice('release_group_ids'))
|
||||
AND af.library_id = ?
|
||||
ORDER BY rgr.disc_number, rgr.track_number;
|
||||
|
||||
@@ -125,3 +125,26 @@ JOIN audio_files af ON af.recording_id = r.id
|
||||
WHERE af.library_id = ?
|
||||
GROUP BY g.id, g.name
|
||||
ORDER BY g.name;
|
||||
|
||||
-- Same as GetFilePathsByReleaseGroups, for "play these genres" (perf.m2):
|
||||
-- one query instead of one per genre, and file paths instead of whole
|
||||
-- track rows, which was 6 MB over the IPC for five genres.
|
||||
|
||||
-- name: GetFilePathsByGenres :many
|
||||
SELECT g.name AS genre_name, af.file_path
|
||||
FROM genres g
|
||||
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||
JOIN recordings r ON rg.recording_id = r.id
|
||||
JOIN audio_files af ON af.recording_id = r.id
|
||||
WHERE g.name IN (sqlc.slice('genre_names'))
|
||||
ORDER BY r.name;
|
||||
|
||||
-- name: GetFilePathsByGenresByLibrary :many
|
||||
SELECT g.name AS genre_name, af.file_path
|
||||
FROM genres g
|
||||
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||
JOIN recordings r ON rg.recording_id = r.id
|
||||
JOIN audio_files af ON af.recording_id = r.id
|
||||
WHERE g.name IN (sqlc.slice('genre_names'))
|
||||
AND af.library_id = ?
|
||||
ORDER BY r.name;
|
||||
|
||||
Reference in New Issue
Block a user