Swift CoreData:访问关系比仅通过谓词获取要慢 - 是这样设计的吗?

Posted

技术标签:

【中文标题】Swift CoreData:访问关系比仅通过谓词获取要慢 - 是这样设计的吗?【英文标题】:Swift CoreData: accessing relationship is slower than just fetching by predicate - is it designed that way? 【发布时间】:2022-01-06 06:43:50 【问题描述】:

在我的应用中,我有 100 个图书馆,每个图书馆包含 5000 本书。

如果我想打印 10 个库和它们最近添加的 10 个,我可以通过访问关系来获取它们,然后 .suffix 返回的 NSSet 并运行 sort 或者我可以通过以下方式找到这些库留下一个libraryID 属性,我以后可以在NSPredicate 中使用,如下所示:

let fetchRequest = ... "Library"
let sort = NSSortDescriptor(key: "some key for ordering", ascending: false)
fetchRequest.sortDescriptors = [sort]
fetchRequest.fetchLimit = 10

let libraries = try context.fetch(fetchRequest) as? [Library]

for library in libraries 

    let fetchRequest = "Book"
    fetchRequest.fetchLimit = 10
    let predicate = NSPredicate(format: "libraryID == %@", library.id ?? "")
    fetchRequest.predicate = predicate
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "added date", ascending: false)]
    
    ...


我不明白为什么第二个选项使用 15% 的 CPU,而直接访问关系却慢了大约 10 倍。

我对数据库的理解是,我们有适当的关系来防止做这类事情,在某种程度上将父属性的 ID 硬编码到子属性中,因为现在我质疑什么关系甚至有好处。

有一件事我可以看到一个有用的关系,即如果我们能够在Library 对象上执行.fetch 或者它是books 关系 - 这可能吗?因为这样我们就不必每次都扫描整个表,而只需在关系的条目中进行搜索。

【问题讨论】:

【参考方案1】:

通过关系访问,然后排序和丢弃 4950 / 5000 个项目意味着所有这些处理都必须在内存中完成。使用获取请求意味着您可以让数据库完成工作。

如果图书馆与其书籍之间存在关系,则可以在谓词中使用它。在你上面的代码中,这将是这样的:

let predicate = NSPredicate(format: "library == %@", library)

这可能比存储 ID 更快,除非您在库 ID 上添加了索引。

【讨论】:

为我节省了 60% 的 CPU 时间。太感谢了。你能花点时间详细说明一下unless you have an index added on library ID吗?这是什么意思? 您可以在核心数据模型编辑器中为字段添加索引,这将为数据库添加索引,可以加快访问速度,但会带来成本(写入速度较慢)

以上是关于Swift CoreData:访问关系比仅通过谓词获取要慢 - 是这样设计的吗?的主要内容,如果未能解决你的问题,请参考以下文章

Swift coreData - 格式化日期并在谓词中使用它

如何为对象计数多个关系创建谓词?核心数据 iOS Swift

swift CoreData 谓词

谓词不适用于 CoreData - Swift 4

核心数据和关系谓词

无法使用 Swift 在 CoreData 中访问一对多关系