I’m dong data processing in a child moc in a background queue. I need to query the database by ID so that I can differentiate updating-existing-object from creating-new-object. I found most of the time(the total processing time is about 2s for 50 items) is consumed by executeFetchRequest:error:. The NSPredicate is of the simplest form — only to match a single ID attribute(ID attribute is already indexed), and the NSFetchRequest should return one or none(ID is unique). Is there any way to optimize this kind of NSFetchRequest?
Here is my current code:
+ (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;
}
}
As @ChrisH pointed out in comments under the question, doing a fetch for every ID is no good. So I changed my processing flow to this:
existingUsers).existingUsersor create a new user, add it intoexistingUsersif it is new.The code is almost doubled, but so is the performance. Really good tradeoff!