我最近做了一些基准测试,看起来像是通过主键查找另一个对象:
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 :)查找的性能是什么?
额外信用:何时使用LinkingObjects
,List
等有用?假设它只是某种可读性/便利性包装器。在我的情况下,它更容易混乱/容易出错,所以我假设我没有按照预期的方式使用Realm。
答案 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-one,many-to-many和inverse关系。例如,O(log t)
可能只有一个Cat
,因此Owner
模型的对象属性指向其Cat
是有意义的。 Owner
可能有多个朋友,因此Person
模型有一个列表属性包含他们所有的朋友(可能包含零个,一个或许多其他Person
)是有意义的
最后,如果您对了解更多内容感兴趣,整个数据库堆栈都是开源的(同步组件除外,它是一个严格可选的外围组件)。您可以找到核心数据库引擎here的代码。我们还有一篇较旧的文章讨论了数据库引擎的高级设计;你可以找到here。