【发布时间】:2012-11-27 02:09:24
【问题描述】:
我正在批量插入核心数据。我有一个人对象,这个人对象有一个名为“otherPeople”的关系,它是一个人的 NSSet。当从下载中批量插入数据时,一切都很好,直到大约 10,000 人被读入,此时批量插入速度减慢到爬行。我每插入 500 次就保存和重置我的 NSManagedObjectContext。
如果我注释掉插入“otherPerson”关系的部分,批量插入在整个下载过程中会很快。 parseJSON 在 500 个 JSONKit 字典中被批量调用。
任何想法可能导致这种情况?可能的解决方案?
代码:
- (NSArray*) getPeople:(NSArray*)ids
{
NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
[request setEntity:entityDescription];
[request setFetchBatchSize:ids.count];
//Filter by array of ids
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"externalId IN %@", ids];
[request setPredicate:predicate];
NSError* _error;
NSArray* people = [context executeFetchRequest:request error:&_error];
return people;
}
- (void) parseJSON:(NSArray*)people
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSMutableArray* idsToFetch = [NSMutableSet setWithCapacity:CHUNK_SIZE * 3];
NSMutableDictionary* existingPeople = [NSMutableDictionary dictionaryWithCapacity:CHUNK_SIZE * 3];
// populate the existing people dictionary first, that way we know who is already in the context without having to do a fetch for each person in the array (externalId IS indexed)
for (NSDictionary* personDictionary in people)
{
// uses JSON kit to parse out all the external ids...
[PersonJSON addExternalIdsToArray:idsToFetch fromDictionary:personDictionary];
}
// see above code for getPeople implementation...
NSArray* existingPeopleArray = [self getPeople:idsToFetch];
for (Person* p in existingPeopleArray)
{
[existingPeople setObject:p forKey:p.externalId];
}
for (NSDictionary* personDictionary in people)
{
NSString* externalId = [personDictionary objectForKey:@"PersonId"];
Person* person = [existingPeople objectForKey:externalId];
if (person == nil)
{
// the person was not in the context, make a new person in the context
person = [[self newPerson] autorelease];
person.ancestryId = externalId;
[existingPeople setObject:person forKey:person.externalId];
}
// use JSON kit to populate the core data object...
[PersonJSON populatePerson:person withDictionary:personDictionary inContext:[self context]];
// these are just objects that contain an externalId, showing that the link hasn't been setup yet
for (UnresolvedOtherPerson* other in person.unresolvedOtherPeople)
{
Person* relatedPerson = [existingPeople objectForKey:other.externalId];
if (relatedPerson == nil)
{
relatedPerson = [[self newPerson] autorelease];
relatedPerson.externalId = other.externalId;
[existingPeople setObject:relatedPerson forKey:relatedPerson.externalId];
}
// add link - if I comment out this line, everything runs very fast
// if I don't comment out, things slow down gradually and then exponentially
[person addOtherPersonsObject:relatedPerson];
}
self.downloaded++;
}
[pool drain];
}
【问题讨论】:
-
Instruments 有一个可以在 iOS 模拟器中运行的 Core Data 仪器。我建议您使用它来跟踪 CoreData 正在做什么。
-
您是否有两个实体,即一个
Person实体和一个People实体,还是只有一个实体Person与其他Person实体具有一对多关系? -
你设置
otherPeople关系的代码,你注释掉的代码,可能会有帮助。 -
这是多对多的关系。代码只是遍历数据结构数组,创建新的 Person 对象并调用 addOtherPeopleObject 来添加它们。
-
请回答 TechZen 的问题:一两个不同的实体?代码?
标签: objective-c ios core-data