核心数据搜索优化

ind*_*gie 6 macos performance core-data objective-c nsfetchrequest

我正在开发一个基于核心数据的应用程序中的搜索功能,我正在尝试收集每个人的搜索优化提示,以尽可能快地获取它.搜索需要足够快,以便为20,000多个对象的数据库提供近乎即时的结果.

到目前为止我做了什么(就优化而言)

  • 实现WWDC 2010会话137中显示的技术,创建关键字实体并创建从主要对象实体到其的多对多关系.name索引关键字实体的属性,并在初始导入过程中通过拆分主要实体中的相关字符串并对其进行规范化来创建关键字(剥离大小写和变音符号)
  • 使用>=<二进制比较器代替BEGINSWITH,等等.我的谓词格式是:

SUBQUERY(keywords, $keyword, ($keyword.name >= $LB) AND ($keyword.name < $UB)).@count != 0

$LB下界字符串在哪里,$UB是上限.我AND使用此格式和搜索项数组创建复合谓词.

现在,我正在执行一次获取(当用户键入第一个字母时)使用大约20的获取批量大小,然后在继续键入时使用NSArray的-filteredArrayUsingPredicate方法缩小搜索结果.我也预取了这个keywords关系,因为它用于过滤.显然,占用时间最多的部分是初始提取.在大约15,000个对象的库上有大约1-2秒的显着延迟.时间分析表明它确实是导致延迟的提取:

http://cl.ly/3a1b2022452M2V323f2H

值得注意的另一件事是我必须为结果获取多个实体.所有实体都有一个ranking属性,但我不能一次获取多个实体,因此我不得不单独获取它们,将它们组合成一个数组,然后通过手动排序-sortedArrayUsingDescriptors.

任何有关如何提高速度的提示都将不胜感激.

编辑:基于@ImHuntingWabbits的建议:

添加KeywordFirstChar实体后,我的数据模型(简化)将如下所示:

新模式

现在,问题是如何为Car基于提取的实体编写谓词KeywordFirstChar?我唯一能想到的就是:

SUBQUERY(keywords, $keyword, $keyword.firstChar.char == %@)%@要搜索的字符在哪里,但我不知道如果它仍然需要枚举keywords,这会更有效率,除非我误解了这些建议.

ImH*_*its 4

您的查询经过高度优化,我认为您已经采取了很多步骤。就第一个字符而言,你做错了。

您仍在扫描 15k 条记录来查找第一个字符命中,并且可能匹配其中的大量记录。

您可以通过索引关键字索引来进一步优化它,创建两个新实体:

  • 关键字第一个字符
  • 关键字前两个字符

两者都与它们指向的关键字具有一对多关系。

if (searchPredicate.length == 1) {
    //search on KeywordFirstChar
} else if (searchPredicate.length == 2) {
    //search on KeywordFirstTwoChars
} else {
    //search on keyword
}
Run Code Online (Sandbox Code Playgroud)

这样,您的表扫描将分别最多扫描 26 行和 676 行,这应该是相当简单的。只需确保该关系位于提取请求上的预取关系键路径中,以便您确实从磁盘中获取数据。

编辑(对象检索):

您可以遵循关系关键路径,因此它会是这样的:

 [fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:@"keyword.sourceObject"]];
Run Code Online (Sandbox Code Playgroud)

其中keyword是与Keyword实体的关系,sourceObject是您想要最终检索的对象。

编辑(谓词):

谓词本质上是相同的,只是更改名称以匹配新实体(名称可能不会映射到名称,而是firstChar或其他一些属性)。