Локальные музыкальные серверы при масштабировании медиатеки нередко сталкиваются с нелинейным ростом задержек во время глубокой пагинации и комплексных агрегаций. Для фиксации реальных эксплуатационных параметров мы выполнили замеры задержек на путях чтения протокола Subsonic в PureStream на тестовом наборе из 500 000 треков.
Объем тестирования и построение данных
Медиатеки коллекционеров регулярно насчитывают сотни тысяч аудиозаписей. Востребованные точки протокола Subsonic (перечисление search3, навигация по каталогу getMusicDirectory, просмотр альбомов getAlbumList2) имеют различную вычислительную сложность. Часть запросов опирается на покрывающие индексы, тогда как другие требуют дедупликации по всей таблице. В рамках данного этапа выполнены следующие шаги:
- [x] Формирование тестового каталога на 500 000 записей (~42 000 альбомов, 2 000 артистов, 100 жанров) через стандартный процесс миграций для создания базы SQLite, идентичной рабочей среде
- [x] Создание покрывающего индекса чтения для запросов по жанрам с регистрацией в схеме данных для предотвращения случайного удаления
- [x] Замер профилей задержки P50 и P95 для 14 ключевых сценариев чтения для формирования базового отчета
Показатели основных сценариев чтения
| Точка вызова | 100k | 500k | Оценка |
|---|---|---|---|
| search3 основное перечисление | 53µs | 69µs | Стабильно |
| search3 глубокая страница (offset=250k) | — | 25ms | Стабильно |
| getMusicDirectory отдельная страница | 1.3ms | 1.4ms | Стабильно |
| getAlbumList2 три режима пейджинга | 8–82ms | 86–333µs | Стабильно |
| getSongsByGenre | не замерялось | 113µs | Индекс эффективен |
| FTS текстовый поиск | 24.8ms | 137ms | Линейный рост |
| getArtists дедупликация | 3.4ms | 543ms | Нагрузка агрегации |
| getGenres агрегация | не замерялось | 600ms | В пределах нормы |
| Объемный отдельный каталог (глубокая страница) | — | 734ms | Граничный случай |
Основные результаты наблюдений:
- Основное перечисление (69 мкс): Запрос по умолчанию search3 выполняется за микросекунды на массиве из 500 000 записей. Применение частичного покрывающего индекса на активные строки изолирует чтение от фоновой записи сканера каталога.
- Глубокий пейджинг (25 мс): Получение одной страницы со смещением в 250 000 треков занимает 25 миллисекунд, обеспечивая миллисекундный отклик при значительных смещениях.
- Выборка по жанрам (113 мкс): Новый покрывающий индекс переводит план запроса с полного сканирования таблицы на поиск по индексу, ощутимо уменьшая задержку.
Анализ участков повышенной вычислительной нагрузки
Тестирование выявило два сценария группировки с повышенными требованиями к ресурсам:
- getArtists дедупликация (543 мс): Объединение основных и приглашенных исполнителей с последующей группировкой требует последовательного сканирования всей таблицы. На 500 000 треков время выполнения не превышает секунды, сценарий находится на мониторинге.
- getGenres агрегация (600 мс): Расчет уникальных альбомов через
COUNT(DISTINCT album)занимает около 600 миллисекунд при объеме в 500 000 записей.
Результаты оптимизации
- [x] Сформированы базовые замеры P50/P95 для 14 точек чтения на объеме 500 000 треков
- [x] Развернут индекс чтения по жанрам с регистрацией в схеме и проверкой планов выполнения
- [x] Зафиксированы и оценены ключевые точки затрат в операциях группировки для будущих улучшений
Планы дальнейшей разработки
- [ ] Модернизация пагинации протокола: Внедрение курсорной навигации для методов без параметра offset
- [ ] Оптимизация проверок авторизации сессий при непрерывном воспроизведении
