本地流媒体服务在海量曲目场景下,深层分页与特定聚合查询的延时容易出现非线性增长。针对大曲库的实际运行负载,我们在包含 500,000 首曲目的基准环境下对 PureStream 的 Subsonic 协议读路径进行完整性能采样,记录各项接口在规模化数据集下的真实响应时间。
测试背景与环境构建
发烧友用户的本地曲库常达到数十万首规模。Subsonic 协议常用接口(包括 search3 枚举、getMusicDirectory 目录检索、getAlbumList2 专辑列表)在不同数据体量下的开销特征存在明显差异,部分查询支持覆盖索引,部分接口则依赖去重与分组聚合。为了准确掌握各路径的负载特征,本次测试执行了以下工作:
- [x] 合成测试数据集:构建 50 万条媒体记录(覆盖约 4.2 万张专辑、2000 位艺人与 100 个流派),完成全量迁移流程,生成与生产环境同构的 SQLite 数据库
- [x] 补充流派索引:为流派查询建立覆盖读索引,并加入数据库架构校验流程,防止索引缺失或异常变更
- [x] 基线采样记录:对 14 条核心读路径进行 P50 与 P95 延时采样,生成基准性能分析记录
核心读路径测试数据
| 接口 | 100k | 500k | 判定 |
|---|---|---|---|
| search3 主枚举 | 53µs | 69µs | 稳定 |
| search3 深偏移页(offset=25万) | — | 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µs):search3 默认查询在 50 万条记录下保持微秒级响应。该路径采用过滤缺失记录的部分覆盖索引,在后台目录扫描器持续写入时依然能够保证读取效率。
- 深偏移分页(25ms):在第 25 万首曲目偏移位置读取单页,查询耗时为 25 毫秒,在大跨度偏移下维持在毫秒级处理周期。
- 按流派筛选(113µs):通过引入覆盖索引,该接口的查询计划由全表扫描优化为索引扫描,执行时间显著压缩。
性能瓶颈分析
基准测试同时量化了计算复杂度较高的两个查询场景:
- getArtists 去重枚举(543ms):艺人去重需要对主要艺人与参与艺人两个字段执行并集与分组聚合,各页查询均需遍历全表。在 50 万首曲目规模下耗时保持在亚秒级,当前已列入技术观察列表。
- getGenres 聚合统计(600ms):流派统计包含针对独立专辑的去重计数(
COUNT(DISTINCT album)),需要进行分组聚合运算,在 50 万首规模下耗时约为 600 毫秒。
优化成果
- [x] 完成 50 万首曲目规模下 14 个核心读接口的 P50/P95 性能采样
- [x] 落地流派只读索引,补齐数据库架构变更登记与执行计划断言校验
- [x] 完成去重与聚合场景的性能热点量化与调优方向梳理
后续演进规划
- [ ] 协议层分页机制升级:针对缺少 offset 参数的接口引入游标分页,降低深页扫描开销
- [ ] 实时流媒体传输鉴权与会话查询合并优化
