我在后台队列中的子moc中进行数据处理。我需要通过ID查询数据库,以便我可以区分updated-existing-object和creation-new-object。我发现大部分时间(50个项目的总处理时间约为2秒)由executeFetchRequest:error:
消耗。 NSPredicate
是最简单的形式 - 仅匹配单个ID属性(ID属性已编入索引),NSFetchRequest
应返回一个或不返回(ID是唯一的)。有没有办法优化这种NSFetchRequest
?
这是我目前的代码:
+ (User *)userWithID:(NSNumber *)ID inManagedObjectContext:(NSManagedObjectContext *)context {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"User"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ID == %@", ID];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchBatchSize:1];
NSError *error = nil;
NSArray *users = [context executeFetchRequest:fetchRequest error:&error];
if (error) {
abort();
}
if ([users count] == 1) {
return [users objectAtIndex:0];
} else if ([users count] > 1) {
// Sanity check.
…
} else {
return nil;
}
}
答案 0 :(得分:1)
正如@ChrisH在问题的评论中指出的那样,对每个ID进行一次获取并不好。所以我将处理流程改为:
existingUsers
)。existingUsers
中找到的现有用户或创建新用户,如果是新用户,请将其添加到existingUsers
。< / LI>
醇>
代码几乎翻了一倍,但性能也是如此。非常好的权衡!
答案 1 :(得分:1)
为了扩展我对原始问题的评论,在导入数据时重复执行使用Core Data的获取请求效率不高。
最简单的方法,如@ an0所示,是对要检查的所有现有对象执行一次提取,然后构造一个包含具有您将检查为键的属性的对象的NSDictionary。所以坚持使用原始的User和userID示例:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"User"];
NSError *error = nil;
NSArray *users = [context executeFetchRequest:fetchRequest error:&error];
if (error) {
//handle appropriately
}
NSMutableDictionary *userToIdMap = [NSMutableDictionary dictionary];
for (User *user in users){
[userToIdMap setObject:user forKey:user.ID];
}
现在,在处理新数据的方法中,您可以检查userToIdMap
字典,而不是制作提取请求。
核心数据编程指南Efficently Importing Data中概述了适用于更大数据集的更复杂方法。看看“有效实现查找或创建”一节。 Apple建议的方法错过了一些关于如何遍历你创建的数组的代码,我对这个问题的解决方案就是在这个问题中:Basic array comparison algorithm