我在.txt文件中有16000条记录,我希望使用核心数据在数据库中插入所有数据。
但是操作性能不好,从.txt文件到数据库(使用CoreData)读取-插入数据需要很长时间。
在安卓系统中,我使用SQLite事务来实现最好的性能,而且它运行得很好。但在iOS,我找不到办法。
注意:我已经尝试过以下文章,但所有提供的参考URL都显示了错误404:iOS CoreData批处理插入?
发布于 2015-10-09 00:39:56
您希望使用完全独立的堆栈进行保存(在私有队列上创建一个新的持久存储协调器和托管对象上下文)。这是为了在默认情况下利用iOS7+中的WAL - on。这允许您在不阻塞正在阅读的上下文的情况下进行写作。
您还希望分批导入,每个批在自己的自动释放池中。保存并重置MOC。
我忽略了这个例子中的错误,为了一个与处理错误无关的示例的清晰性.别那么做..。
- (void)importFromURL:(NSURL*)url batchSize:(NSUInteger)batchSize {
// Open the URL so it can be used to read the text file
// Create a new PSC, attached to the same store(s) as the PSC used by main context
NSManagedObjectModel *model = // same MOM used by your main context
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:NULL];
// A private-queue MOC
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.persistentStoreCoordinator = psc;
moc.undoManager = nil;
// Load all objects from the file, in batches
NSUInteger total = 0;
Record *record = nil;
do {
NSUInteger count = 0;
@autoreleasepool {
while (count < batchSize && (record = [self fetchNextRecord]) != nil) {
[self createManagedObjectFromRecord:record inManagedObjectContext:moc];
++count;
}
[moc save:NULL]; // don't ignore the error
[moc reset];
}
total += count;
} while (record != nil);
// Post a notification indicating that the import has finished.
// This allows your main context to refetch from the store.
[[NSNotificationCenter defaultCenter] postNotificationName:@"DidImport" object:self userInfo:@{ @"url":url, @"total":@(total)}];请注意,这假设您没有任何关系,并且只是加载直接的对象。
如果您有关系,您应该先加载对象,然后再建立关系。
如果您的数据集更像是一组相关对象的小集群,那么您应该将每个小集群作为一个批处理加载,加载对象,然后连接关系,然后保存并移动到下一个批处理。
那么,这个示例代码是干什么的呢?
它创建了一个完全独立的核心数据堆栈,允许在导入过程中更好地并发。
它以小批方式装载对象。这样可以防止内存分配失控,并使更新大小易于管理。如果您有另一个上下文,观察更改并自动合并它们,这将有所帮助。小型批处理对执行合并的其他线程的影响较小。
在每个批处理将数据提交到存储区后进行保存。重置上下文将释放与上下文关联的任何内存,并允许下一批处理重新开始。这有助于限制内存的增长。
自动释放池确保在每个批处理结束时释放任何自动释放的对象,这也有助于减少内存占用。
最后的通知允许通知其他代码,以便从实际的核心数据数据库文件中重新获取。
对于非常大的导入,这可能比每次观察上下文的保存和合并要有效得多。
这显然不是工作代码,但它向您展示了应该如何进行。如果您遵循此模板,您应该能够快速、高效地导入。
发布于 2015-10-08 11:37:13
由于数据是静态的,所以只需通过Core数据将所有数据预加载到sqlite文件中即可。你可以读到关于那个这里的文章。
发布于 2015-10-09 23:12:57
按照以下建议可以轻松高效地完成这一任务:
@autoreleasepools优化内存undoManager (将其设置为nil)在保存工作上下文时,UI被高效更新(全部在内存中),而数据创建和物理数据库保存的繁重工作是在后台完成的。
这在从CSV文件中插入200.000+记录时执行得很好。
请注意,在模拟器中完成所有这些操作(即使没有优化),然后按照其他地方的建议将完成的数据库sqlite文件放入包中也是可行和良好的做法。
https://stackoverflow.com/questions/33014024
复制相似问题