有什么方法可以优化单个对象的简单NSFetchRequest?

时间:2012-10-02 16:14:46

标签: ios core-data nsfetchrequest

我在后台队列中的子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;
    }
}

2 个答案:

答案 0 :(得分:1)

正如@ChrisH在问题的评论中指出的那样,对每个ID进行一次获取并不好。所以我将处理流程改为:

  1. 首次枚举数据以提取ID。
  2. 执行单次提取以获取与ID匹配的所有现有用户,并将其放入按ID键入的字典中(命名为existingUsers)。
  3. 第二次枚举数据以进行实际处理:在每次迭代中,更新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