Commit 753556a
perf(backend): materialize virtual collection membership
virtual_collections was a view that unnested five JSON arrays per rom on
every read, so both the collection list and opening a single collection
scanned the whole library. Opening a collection with a handful of roms
cost as much as one with thousands, since the name is computed inside the
view and nothing can be narrowed down early.
Membership now lives in virtual_collection_roms, one narrow row per
(type, name, rom_id) plus that rom's covers, derived from the generated_*
columns and maintained by triggers on roms (deletions ride the foreign
key cascade). The view becomes a plain aggregate over that table, so the
model, schemas and API shape are unchanged, and filtering roms by a
virtual collection is an indexed subquery instead of an IN list of every
member id.
Covers are no longer aggregated in the view, which materialized every
member's cover path on every request; the handler resolves at most five
per collection, matching the smart collection cap and what both UIs
render.
On a synthetic 50k-rom library the list goes from 1.42s to 0.128s and a
single collection from 0.111s to 0.0006s, with identical output.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent ab59f32 commit 753556a
6 files changed
Lines changed: 666 additions & 16 deletions
File tree
- backend
- alembic/versions
- handler/database
- models
- tests/handler/database
- docs
0 commit comments