在Realm中进行主键查找的性能?

时间:2017-10-24 22:23:05

标签: ios swift performance realm

我最近做了一些基准测试,看起来像是通过主键查找另一个对象:

let foo = realm.object(ofType: Bar.self, forPrimaryKey: id)

比尝试将属性直接设置为:

更有效(并且在此特定情况下更具可读性)
class Other: Object {
    @objc dynamic var relation: Bar? = nil
    let list = List<Bar>()
}

我的基准测试不是太彻底(在列表中只使用了一个元素,等等),我想知道这是否真的如此。

Intuition让我认为主键查找和使用上面的relation属性将是O(1)或O(logn)。拥有1,000,000条记录和1,000,000条查询:

  

主键:~10s

     

relation属性:~12s

     

list财产:~14s

总结:Realm的对象(ofType:forPrimaryKey :)查找的性能是什么?

额外信用:何时使用LinkingObjectsList等有用?假设它只是某种可读性/便利性包装器。在我的情况下,它更容易混乱/容易出错,所以我假设我没有按照预期的方式使用Realm。

1 个答案:

答案 0 :(得分:2)

Realm不是像SQLite这样的关系数据库。相反,数据存储在B+ trees中。给定模型类型上给定属性的所有数据都存储在一个树中,所有数据检索(无论是获取属性值还是链接对象)都涉及遍历这样的树。

此外,打开Realm时,整个数据库文件的内容都会mmap进入内存。当您使用其中一个Realm SDK时,您创建的对象(例如Object个实例)实际上是瘦包装器,它存储指向数据库文件中某个位置的概念指针,并提供直接读取和写入对象的方法在那个位置。同样,关系(例如模型上的对象属性)是对树中其他位置的节点的引用。

这意味着检索对象需要遍历数据库数据结构以查找所需信息所花费的时间,以及实例化对象并初始化它所花费的时间。后者实际上是一个恒定时间操作,因此我们希望主要关注前者。

至于你概述的情况......

  • 如果您已经知道主键值,则获取对象需要O(log n)次,其中n是数据库中该特定类型的对象数。 (检索Dog所花费的时间与数据库包含的Cat的数量无关。)
  • 如果你天真地实现了一种关系型外键模式,你可以通过在{{{}}类型的某个对象上存储主键值(如字符串)来建模类型为U的对象的链接。 1}},需要T时间来检索主键值(其中O(log t)t s的数量),T时间查找目的地对象(如上一个项目符号点所述; O(log u) = u s的数量。
  • 如果您在模型类型U上使用对象属性来建模到另一个对象的链接,则需要T时间来检索目标对象的位置。
  • 使用列表引入了另一个间接层,因此从单个对象列表中检索单个对象比直接从对象属性检索对象要慢。

对象,列表和链接对象属性不是用于通过主键查找对象的替代方法。相反,它们分别用于建模many-to-onemany-to-manyinverse关系。例如,O(log t)可能只有一个Cat,因此Owner模型的对象属性指向其Cat是有意义的。 Owner可能有多个朋友,因此Person模型有一个列表属性包含他们所有的朋友(可能包含零个,一个或许多其他Person)是有意义的

最后,如果您对了解更多内容感兴趣,整个数据库堆栈都是开源的(同步组件除外,它是一个严格可选的外围组件)。您可以找到核心数据库引擎here的代码。我们还有一篇较旧的文章讨论了数据库引擎的高级设计;你可以找到here