我有一个NSFetchedResultsController和存储在Core Data中的大量数据,读取的结果控制器必须提取这些数据。最终会有大约46,000件物品被拿走。问题是获取时间超过8秒,整个时间,UI被冻结,因为我们必须在主线程上获取。我想知道我能做些什么来加快这个速度吗?
我按照创建日期对对象进行排序,获取请求的批量大小为100,谓词不会过于复杂。它按照UID,类型和所有者的UID过滤对象。
由于用户可以进行搜索,因此获取谓词将会发生变化,因此每次获取谓词更改时,只需删除获取的结果控制器上的缓存就显得毫无意义。
它与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];
}
答案 0 :(得分:2)
由于您(在评论中)解释了所有属性都是字符串,因此您可能很难改善这种情况。你在fetch中做了很多的字符串比较 - 前两个谓词的46k记录乘以至少3,加上更多取决于平均有多少stories
个关系。这是导致性能问题的主要原因 - 做很多字符串比较会成为瓶颈。
可能有所帮助的一些事情:
@"(ANY stories.permission.owner_person_uid == %@ OR stories.@count == 0)"
。谓词从左到右进行评估。数字比较比字符串比较更快,因此首先进行@count
检查。如果这是真的那么下半部分将不需要进行评估,你将跳过大量的字符串比较。NSPredicate
个实例的顺序。您可能已经知道数据的样子 - 确保最严格的谓词(即最大数量的对象将不通过的谓词)是第一个一个在列表中。然后是第二个最具限制性的,等等。由于你将谓词放在一起,一个实例失败,第一个谓词将不需要与其他谓词进行检查。尽可能早地在谓词链中过滤掉对象。最简单的收益可能是通过更改第三个谓词中的顺序,然后将其移到列表的前面。
答案 1 :(得分:0)
我认为如果这对性能至关重要,您可以随时对数据模型进行去标准化。您可以将一个owner_person_uid属性的副本添加到stories对象中。这样,谓词就不必遍历如此多的关系。
如果您更改其中一个属性,此解决方案将要求您始终更新相关对象。