Speed up metadata cache browser: add composite indexes, remove full-scan LIKE filters

This commit is contained in:
Broque Thomas 2026-03-22 23:13:34 -07:00
parent 203f317236
commit d8217d66ba
2 changed files with 9 additions and 8 deletions

View file

@ -359,10 +359,6 @@ class MetadataCache:
where_clauses = ['entity_type = ?']
params = [entity_type]
# Exclude pseudo-entities like album_id_tracks and track_id_features
where_clauses.append(r"entity_id NOT LIKE '%\_tracks' ESCAPE '\'")
where_clauses.append(r"entity_id NOT LIKE '%\_features' ESCAPE '\'")
if source:
where_clauses.append('source = ?')
params.append(source)
@ -384,6 +380,7 @@ class MetadataCache:
sort = 'last_accessed_at'
direction = 'ASC' if sort_dir == 'asc' else 'DESC'
# Don't select raw_json — it's huge and only needed for detail view
cursor.execute(f"""
SELECT id, source, entity_type, entity_id, name, image_url,
genres, popularity, followers,
@ -475,12 +472,10 @@ class MetadataCache:
'newest': None,
}
# Count by type and source (exclude pseudo-entities like _tracks, _features)
cursor.execute(r"""
# Count by type and source — fast via idx_mce_stats covering index
cursor.execute("""
SELECT entity_type, source, COUNT(*) as cnt, SUM(access_count) as hits
FROM metadata_cache_entities
WHERE entity_id NOT LIKE '%\_tracks' ESCAPE '\'
AND entity_id NOT LIKE '%\_features' ESCAPE '\'
GROUP BY entity_type, source
""")
type_key_map = {'artist': 'artists', 'album': 'albums', 'track': 'tracks'}

View file

@ -3297,6 +3297,12 @@ class MusicDatabase:
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_artist ON metadata_cache_entities (artist_name COLLATE NOCASE)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_accessed ON metadata_cache_entities (last_accessed_at)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_source ON metadata_cache_entities (source)")
# Composite indexes for browse queries (entity_type + sort column)
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_browse ON metadata_cache_entities (entity_type, source, last_accessed_at DESC)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_browse_name ON metadata_cache_entities (entity_type, source, name COLLATE NOCASE)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_browse_pop ON metadata_cache_entities (entity_type, source, popularity DESC)")
# Stats query index (covers GROUP BY entity_type, source with count)
cursor.execute("CREATE INDEX IF NOT EXISTS idx_mce_stats ON metadata_cache_entities (entity_type, source, access_count)")
cursor.execute("""
CREATE TABLE IF NOT EXISTS metadata_cache_searches (