一种从indexedDB对象存储中删除缺少属性的对象的有效方法

An efficient way of removing objects from an indexedDB object store that are missing a property

本文关键字:对象 删除 属性 方法 有效 存储 一种 indexedDB      更新时间:2023-09-26

我正在思考如何使我的一个项目中的某个操作更有效率。当前实现中的操作从对象存储中加载所有对象,遍历数组并测试对象是否缺少属性或属性是否未定义,在第二个数组中收集这些对象的集合,然后删除所有这些对象。

我已经在使用gettall了,因为它比游标迭代有明显的性能优势。

我同时调用单独的删除请求,所以没有速度,但indexedDB api发展到支持批量删除的非索引的非keypath道具是缺失的值。

问题是,如果不将每个对象完全加载到内存中,当属性不在对象存储的键盘中时,我没有办法检查属性。在某些情况下,对象相当大。有时,每个对象的其中一个属性非常大(本质上是html文档的字符串)。

我不能使用索引,因为对象中不存在的属性,或者没有值的属性,不会出现在索引中。

是否有一种方法可以避免将这样的对象加载到内存中?

我考虑过分区,并使用两个对象存储,一个用于可查询的道具,一个用于完整的数据。但这就意味着每次读取都必须执行额外的请求。我的应用程序做了更多的读取,而不是偶尔的批量删除操作。

我想过为每个对象存储一个额外的属性,它总是有一个像myObject.doesOtherPropertyHaveValue这样包含0/1的值,因此是可索引的,但这似乎也不太好。当然,我可以通过这个索引查询,并使用getAllKeys,这就解决了问题。但是,现在每个add/put都必须维护这个功能依赖。

如果记录的形式为{key, prop},其中prop可能不存在,则可以在[key, prop]上创建索引。只有当prop存在时,才会有索引记录。然后打开两个仅键游标:一个在存储(C1)上,另一个在索引(C2)上。检查一下C1。primaryKey = C2.primaryKey[0]。如果是,道具存在,推进两者。如果键相等,则C1指向没有prop的记录;删除它并推进C1。重复。(当您到达范围的末尾时,要注意边缘情况。)

这有两个问题:(1)你仍然使用游标,所以仍然支付往返的成本(不像getAll()),(2)如果prop很大(即你提到的HTML文档的主体),那么即使只是使用键游标,你仍然在打乱大量的数据。

(将来我们希望通过添加更通用的查询机制或自定义索引(可能与delete-on-index相结合)来解决这个问题,这两种方法都会使这个问题更容易、更有效)

…在第二个数组中收集这些对象的集合,然后删除所有这些对象…

如果你坚持这种方法,记住你可以发出delete()调用,因为你发现他们;不需要收集所有对象,也不需要等待删除完成;您可以以"即发即弃"的方式使用IDB进行写操作。

您在正确的道路上,非规范化可能是提高性能所必需的。不幸的是,从indexedDB文档中没有办法查询您需要的方式。

如果真正的瓶颈是I/O或将数据编组到JS-land,那么也许可以尝试在写入数据之前压缩数据,并在实际需要对数据进行处理时解压缩数据?GZIP可以很好地压缩文本,有时最多可以压缩70%。有几个GZIP库可以为JS工作:

https://github.com/nodeca/pako

但是,一如既往,基准!