高效管理多个对象存储空间需结构清晰、职责分明、访问可控:按业务域划分空间(如filetree、board、tldraw),各配独立typescript接口、定制索引(by_path、updatedat、userid)、专属工具类封装事务,并定期巡检清理。

高效管理多个对象存储空间,关键在于结构清晰、职责分明、访问可控。不是堆得越多越好,而是每个空间承担明确角色,彼此解耦又协同。
按业务域划分对象存储空间
避免把所有数据塞进一个“万能表”。比如笔记应用里,fileTree 存目录结构,board 存白板快照,tldraw 存绘图元数据——三者数据模型、读写频率、生命周期都不同。分开建空间后,升级某一块(如只改白板格式)不会波及其他模块。
- 每个空间对应一个独立的 TypeScript 接口定义,类型安全更易维护
- 删除某类数据时,直接调用
deleteObjectStore()即可,不污染其他数据 - 事务操作可精准控制范围,例如仅对
board空间开启 readwrite,不影响fileTree的并发读取
统一事务封装,避免跨空间误操作
多个空间共用一个数据库,但不能在一次事务里混写不同空间——这会增加锁竞争、降低并发性,也违背单一职责。推荐做法是:每个空间的操作由专属工具类封装,内部自动创建对应事务。
- 例如
BoardIndexedDB.addSnapshot()内部只打开board空间,不碰tldraw - 需要跨空间强一致性场景(如新建笔记同时生成初始白板),才显式启动多空间事务:
db.transaction(['fileTree', 'board'], 'readwrite') - 所有工具类共享同一个数据库实例(单例),避免重复打开连接
索引策略按空间定制,不一刀切
不同空间的查询模式差异很大。目录树常按路径模糊匹配,白板按修改时间排序,绘图数据则可能按协作用户 ID 查询——索引必须跟着使用方式走。
-
fileTree空间建path索引支持前缀查询(如path.startsWith('/project/a/')) -
board空间建updatedAt索引用于最近编辑排序 -
tldraw空间建userId索引便于协作场景快速过滤 - 索引名保持语义化(如
'by_path'而非'idx1'),方便后续维护
定期清理与空间健康检查
多个空间长期运行后,容易出现碎片、冗余或过期数据。需建立轻量级巡检机制:
- 在应用启动或空闲时,检查各空间记录数与预期是否偏差过大(如
tldraw空间条目远超当前打开的白板数,可能缓存泄漏) - 为每类空间设置 TTL 字段(如
expiresAt),用游标遍历 + 条件删除实现低开销清理 - 避免用
clear()清空整个空间,优先用 keyRange 精准移除过期批次











