Umfasst eine lokale Musikbibliothek mehrere hunderttausend Titel, bleibt das Scrollen auf der ersten Anzeigeseite meist flüssig, während tiefes Blättern, Buchstabensprünge und globale Suchen spürbare Latenzen verursachen. Anhand eines Referenzdatensatzes mit 500.500 Titeln haben wir die Ausführungszeiten zentraler Lesepfade gemessen und für Version 7.0 einen lokalen schreibgeschützten Spiegelmechanismus entwickelt.
Versionshinweis: Version 6.0 enthält grundlegende Performance-Optimierungen. Der hier beschriebene Hochleistungs-Lesespiegel ist für Version 7.0 vorgesehen und befindet sich in der internen Testphase. Alle Messwerte stammen aus internen Entwicklungs-Builds.
Die Architektur erzeugt lokal eine abgeleitete, schreibgeschützte SQLite-Kopie der Bibliothek. Während des Indexaufbaus werden Sortierschlüssel, Filterattribute und A-Z-Indexanker vorberechnet und dauerhaft auf der Festplatte gespeichert. Der primäre Systemspeicher behält die Datenhoheit, während der Lesespiegel Abfragen bedient und sich bei Bedarf unabhängig neu aufbauen oder bereinigen lässt.
Gemessene Benchmark-Ergebnisse
Die Messungen erfolgten auf einem M4 Mac mini mit dem Datensatz über 500.500 Titel; alle Werte wurden über feldweise Konsistenzprüfungen validiert:
| Lesepfad | Umfang | Primärspeicher | Spiegel | Beschleunigung |
|---|---|---|---|---|
| Aufbau des Titellisten-Snapshots | 10k | 3030 ms | 21 ms | ~143× |
| Listen-Paging (gefiltert) | 10k | 1984 ms | 8,2 ms | ~242× |
| A-Z-Ankersprung | 10k | ~2050 ms | 0,4–7,6 ms | 274–5100× |
| Tiefe Seite (Offset 450k) | 500k | ~28 Min./Seite | ~0,9 s | ~1800× |
| Null-Treffer-Scan „Sichtbare Zeilen vorhanden?" | 100k | 98,1 s | 46 ms | ~2100× |
| Mehrfachkriterien für Smart-Playlists | 100k | 6,9 s | 1,27 s | ~5,4× |
| Playlist-Ansicht / Künstler-Detail / Erstaufbau | 50k | – | – | 4,5–7,3× |
Bei 500.000 Titeln nutzt der ursprüngliche Pfad vollständige Tabellenscans, sodass die Ausführungszeit mit steigendem Offset stark zunimmt: Das Laden einer einzelnen Seite um Titel 400.000 dauerte als Baseline rund 1668 Sekunden. Der schreibgeschützte Spiegel senkt die Abfragedauer an dieser Stelle auf 0,8 bis 1,4 Sekunden und hält die Zugriffszeit über unterschiedliche Tiefen stabil.
Sortier-Tags und Ansichtenkompatibilität
In Klassik- und Jazzsammlungen aktivieren Hörer häufig Sortier-Tags, um Interpreten wie „The Beatles" unter dem Buchstaben B („Beatles, The") einzuordnen. Der Spiegel hinterlegt für die fünf tag-fähigen Felder jeweils zwei getrennte Sortierschlüssel. Beim Umschalten der Sortier-Tags wählt die Abfrage direkt die entsprechende Spalte aus, wodurch die A-Z-Leiste synchron bleibt, ohne dass der Index neu erzeugt werden muss.
Auch Aggregationsansichten für Alben, Interpreten und Komponisten nutzen Spiegelabfragen. Sind Sortier-Tags in diesen Ansichten aktiv, schaltet das System auf den primären Speicherpfad um, um die exakten Tag-Werte auf Entitätsebene abzubilden. Schreibseitig materialisierte Aggregationstabellen sind für künftige Versionen vorgesehen.
Ressourcenbedarf und Abwägungen
Der Betrieb des lokalen Spiegels erfordert zusätzliche Zeit für den Indexaufbau sowie lokalen Speicherplatz:
- Aufbaudauer: Die vollständige Indexerstellung erfolgt als Hintergrundprozess. Für 500.000 Titel benötigt der erste Aufbau rund 32 Minuten, während die Standardnavigation uneingeschränkt nutzbar bleibt; 50.000 Titel sind in etwa 35 Sekunden verarbeitet.
- Speicherbelegung: Die Spiegeldatei für 500.000 Titel belegt rund 2,1 GB Speicherplatz. Der genaue Verbrauch wird in den Einstellungen ausgewiesen. Bei Deaktivierung bleibt der Index für eine spätere Wiederaufnahme erhalten; eine vollständige Bereinigung ist ebenfalls möglich.
- Schreiblatenz: Änderungen an Titel-Metadaten werden synchron in den Spiegel übertragen, was in Tests rund 20 Millisekunden pro Batch-Commit beansprucht.
Aufgrund dieses Ressourcenprofils bleibt die Funktion standardmäßig deaktiviert und kann in den Einstellungen gezielt für umfangreiche Bibliotheken zugeschaltet werden.
Zentrale Optimierungsmechanismen
- Leichtgewichtige Wertprojektion: Während der reguläre Pfad verwaltete Objektmodelle instanziiert, liest der Spiegel Rohzeilen direkt aus SQLite und bildet sie auf schlanke Werttypen ab, was den Verarbeitungsaufwand im Lebenszyklus minimiert.
- Prädikat-Pushdown: Filterkriterien, Sortierlogik und Deduplizierung werden direkt in der Datenbank-Engine ausgeführt, wodurch Datenmengen vor dem Laden in den Arbeitsspeicher reduziert werden.
- Vorberechnete Sortier- und Indexschlüssel: Normalisierte Sortierschlüssel und A-Z-Buchstabenanker werden beim Indexieren festgeschrieben. Abfragen kombinieren Keyset-Paginierung mit Index-Scans und halten die Antwortzeit auch bei tiefen Seiten konstant.
Datenkonsistenz und Implementierungsdetails
Um die Übereinstimmung der Abfrageergebnisse zwischen Spiegel und Hauptspeicher sicherzustellen, deckt die Testsuite Permutationen aus 19 Sortierspalten, Sortierrichtungen, Tag-Status und kombinierten Filtern ab. Im Zuge der Angleichung wurden mehrere Randfälle adressiert:
- Null-Werte und leere Zeichenketten: Sortier-Tags priorisieren den Tag-Inhalt und greifen bei Fehlen auf den Anzeigenamen zurück. Da Swift-Operatoren und SQL-Funktionen leere Zeichenketten unterschiedlich auswerten, materialisiert der Spiegel Tag- und Anzeigeschlüssel in separaten Spalten und wählt diese bei der Abfrageerstellung explizit an.
- Sortierkompatibilität historischer Felder: Titellaufzeiten wurden historisch per Zeichenkettenvergleich sortiert (beispielsweise „120.0" vor „90.0"). Um bestehende Abläufe nicht zu verändern, erhalten textbasierte Spalten dedizierte Textsortierschlüssel, während numerische Indizes echten Zahlenwerten vorbehalten bleiben.
- Definition von Leerraumzeichen: Da sich die Definitionen von Whitespace in Swift und standardmäßigen SQL-Trim-Funktionen leicht unterscheiden, synchronisiert ein statusbasiertes Flag auf der Schreibseite die Auswertung beider Schichten.
- Segmentierter Hintergrundaufbau: Bei 500.000 Datensätzen führen Volltextsuch-Trigger zu mehrfachen Indexschreibvorgängen, was die Gesamtdauer auf rund 32 Minuten erhöht. Der Aufbauprozess ist segmentiert aufgebaut und unterstützt das Fortsetzen nach Unterbrechungen.
- Koordination paralleler Schreibvorgänge: Werden während eines aktiven Indexaufbaus Metadaten bearbeitet, versieht das System Schreibvorgänge mit monoton steigenden Sequenznummern, sodass Konfliktbehandlungsregeln stets den aktuellen Versionsstand durchsetzen.
Alle Messungen basieren auf Debug-Builds; detaillierte Auswertungsberichte und Testskripte sind im Projektarchiv hinterlegt.
