0

我有一个 NSFetchedResultsController 和存储在核心数据中的大量数据,获取的结果控制器必须获取这些数据。它最终将获取大约 46,000 件物品。问题是获取时间超过 8 秒,并且整个时间,UI 都被冻结,因为我们必须在主线程上获取。我想知道是否有什么办法可以加快速度?

我按对象的创建日期对对象进行排序,获取请求的批量大小为 100,谓词并不过分复杂。它按对象的 UID、类型和所有者的 UID 过滤对象。

由于用户可以搜索,因此 fetch 谓词会发生变化,因此在 fetched results 控制器上设置缓存似乎毫无意义,因为每次 fetch 谓词更改时它都会被删除。

它与 Core Data 中的对象数量直接相关,因为切换到具有较少对象的帐户会显着减少获取时间。(6000 个对象需要不到一秒的时间)。有什么办法可以让这个更具可扩展性?我的代码如下:

- (NSFetchRequest *)getFetchRequest
{
    NSFetchRequest *fetchRequest = [NSFetchRequest requestWithEntityName:@"Photo"];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    [sortDescriptor release];
    [fetchRequest setPredicate:[self getFetchPredicates]];
    [fetchRequest setFetchBatchSize:100];
    return fetchRequest;
}

- (NSPredicate *)getFetchPredicates {
    NSMutableArray *predicates = [NSMutableArray arrayWithObjects:
                                  [NSPredicate predicateWithFormat:@"life_uid == %@",[[LoginManager shared] currentLifeUID]],
                                  [NSPredicate predicateWithFormat:@"(type == %@) OR (type == %@)", TLTypeImage, TLTypeVideo],
                                  [NSPredicate predicateWithFormat:@"(ANY stories.permission.owner_person_uid == %@ OR stories.@count == 0)", [[LoginManager shared] currentPersonUID]],
                                  nil];
    NSArray *filteredMomentIDs = [[self searchTerms] objectForKey:TLLibraryViewControllerSearchTermsPhotoIDsKey];
    if ([filteredMomentIDs count] > 0 && [self searchMode] == kTLLibrarySearchModeTag)
    {
        [predicates addObject:[NSPredicate predicateWithFormat:@"uid in %@", filteredIDs]];
    }
    return [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
}
4

2 回答 2

3

由于您(在评论中)解释所有属性都是字符串,因此您可能很难改善这种情况。您在该 fetch 中进行了大量字符串比较——前两个谓词的 46k 记录乘以至少 3,再加上更多取决于stories平均有多少关系。这是您的性能问题的主要原因 - 进行如此多的字符串比较将成为瓶颈。

有几件事可能会有所帮助:

  • 在您正在查看的第三个谓词中@"(ANY stories.permission.owner_person_uid == %@ OR stories.@count == 0)"。谓词从左到右进行评估。数值比较比字符串比较快,所以@count先检查。如果它是真的,那么后半部分不需要评估,你会跳过很多字符串比较。
  • 从左到右的事情也适用于您的NSPredicate实例的顺序。您可能对数据的外观有所了解——确保最严格的谓词(即最大数量的对象不会通过的谓词)是列表中的第一个谓词。然后是第二个最严格的,等等。由于您将谓词和-ing 在一起,一个实例失败了第一个谓词将不需要与其他谓词进行检查。尽早过滤掉谓词链中的对象。

可能最简单的收获是通过更改第三个谓词中的顺序,然后将其移动到列表的前面。

于 2013-03-02T00:18:39.430 回答
0

我想如果这对性能真的很重要,你总是可以对你的数据模型进行一些反规范化。您可以将 owner_person_uid 属性的副本添加到 stories 对象中。这样谓词就不必遍历这么多关系。

如果您更改其中一个属性,此解决方案将要求您始终更新相关对象。

于 2013-03-02T00:31:48.700 回答