IndexedDB 查询提速关键在于精准建索引与正确查询:只对WHERE常用字段建索引,优先用高选择性字段开头的复合索引,查询须严格匹配索引结构,并用readonly事务和IDBKeyRange优化读操作。

想让 IndexedDB 查询快起来,核心就两条:索引得建对,查询得用对。建错索引或查法不当,哪怕数据只有几千条,也可能卡顿明显。
索引不是越多越好,而是要“按需而建”
每个索引都会拖慢写入速度,还会占用额外存储空间。Mars 项目实测发现,过度索引会让新增一条记录的耗时上升 30% 以上。
- 只给真正用于 WHERE 条件 的字段建索引,比如常用来 filter、sort 或分页的字段
- 避免为低区分度字段单独建索引(如 status: "active"/"inactive"),这类字段单独索引效果差,还浪费资源
- 优先考虑复合索引替代多个单字段索引——例如查“城市+年龄区间”,比分别建 city 和 age 索引更高效
复合索引顺序很关键:高选择性字段放前面
复合索引不是简单拼字段,顺序直接影响是否能命中。比如 ['city', 'age'] 能高效支持“查北京的用户”,也能支持“查北京且年龄在25–35的用户”;但反过来,['age', 'city'] 就无法加速纯按城市查询。
- 所谓“高选择性”,就是取值越分散越好——用户ID > 城市 > 状态
- 如果查询中经常带排序(如
ORDER BY timestamp DESC),把该字段放在复合索引末尾,可避免额外排序开销 - 测试时可用
index.openCursor()+IDBKeyRange.bound()验证是否走索引,而不是靠经验猜测
查询时必须“对号入座”:让条件精准匹配索引结构
建了索引不等于自动生效。IndexedDB 不会自动重写查询逻辑,你写的条件必须和索引键路径一致,才能触发索引扫描。
- 用
index.get()查唯一值(如 email)、index.getAll()查重复值(如 userId) - 多条件查询务必使用
IDBKeyRange构造范围,例如:IDBKeyRange.bound([‘Beijing’, 20], [‘Beijing’, 35]) - 千万别先
store.getAll()再 JS 过滤——10 万条数据加载进内存再筛,性能灾难立现
读操作一律用 readonly 事务,别让它变慢的借口
只读事务不加写锁、不校验一致性状态,执行更快也更安全。很多项目默认用 readwrite,其实毫无必要。
- 所有列表展示、详情查看、统计计数等场景,都应显式指定
'readonly' - 一个事务里不要混读写操作;读多写少的应用,可拆成两个并行事务提升吞吐
- 注意:游标遍历本身不阻塞 UI,但若在 onsuccess 回调里做大量同步计算,仍会卡顿——建议用
setTimeout或queueMicrotask分片处理










