我正在从一个包含大约 20000 个对象的 JSON 文件中解析数据。我一直在运行时间分析器来找出我的瓶颈在哪里并加快解析速度,我已经设法将解析时间减少了 45%,但是根据时间分析器,我有 78% 的时间被context.save()
以及整个解析过程中的大部分重要部分都来 self 称为 NSEntityDescription.insertNewObjectForEntityForName
的地方。
有没有人知道是否有任何方法可以加快速度?我目前每 5000 个对象对我的保存进行一次批处理。我尝试了 100、1000、2000、5000、10000 的分组,我发现 5000 在我运行的设备上是最佳的。我已经阅读了 Core Data Programming Guide但发现它给出的大部分建议是优化大量数据的获取,而不是解析或插入。
答案很可能是,Core Data 有其局限性,但我想知道是否有人找到了进一步优化插入数千个对象的方法。
更新
根据要求提供一些关于我如何处理解析的示例代码
class func parseCategories(data: NSDictionary, context: NSManagedObjectContext, completion: ((success: Bool) -> Void)) {
let totalCategories = data.allValues.count
var categoriesParsed = 0
for (index, category) in data.allValues.enumerate() {
let privateContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
privateContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator!
privateContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
//Do the parsing for this iteration on a separate background thread
privateContext.performBlock({ () -> Void in
guard let categoryData = category.valueForKey("category") as? NSArray else{
print("Fatal Error: could not parse the category data into an NSArray. This should never happen")
completion(success: false)
return
}
let newCategory: Categories?
do {
let newCategory = NSEntityDescription.insertNewObjectForEntityForName("Categories", inManagedObjectContext: privateContext) as! Categories
newCategory.name = category.valueForKey("name") as? String ?? ""
newCategory.sortOrder = category.valueForKey("sortOrder") as? NSNumber ?? -1
SubCategory.parseSubcategories(category.valueForKey("subcategories") as! NSArray, parentCategory: newCategory, context: privateContext)
} catch {
print("Could not create the Category object as expected \(error)")
completion(success: false)
}
do {
print("Num Objects Inserted: \(privateContext.insertedObjects.count)") //Num is between 3-5k
try privateContext.save()
} catch {
completion(success: false)
return
}
categoriesParsed+=1
if categoriesParsed == totalCategories{
completion(success: true)
}
})
}
}
在上面的代码中,我查看了我称之为“类别”的顶级数据对象,我为每个对象分离了后台线程以同时进行解析。这个顶级对象只有 3 个,因此线程不会太重。
每个类别都有子类别,以及其他几个级别的子对象,每个子对象都会产生数千个插入的对象。
我的核心数据堆栈配置了一个 sqlite 数据库,这是使用 CoreData 创建应用程序时配置的标准方式
最佳答案
一个原因是您要在每次迭代中保存托管对象上下文,这既昂贵又不需要。插入最后一项后保存。
关于ios - 核心数据插入和保存缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35490799/