核心数据插入和保存缓慢

时间:2016-02-18 19:34:35

标签: ios swift parsing core-data optimization

我正在解析具有大约20000个对象的JSON文件中的数据。我一直在运行时间分析器来弄清楚我的瓶颈在哪里并加快解析速度,并且我设法将解析时间减少了45%,但是根据时间分析器我78%的时间是被context.save()占据,整个解析中的大部分重要部分都来自我称之为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个,因此它不会过于繁重。

每个类别都有SubCategories,还有几个其他级别的子对象,每个对象产生几千个对象。

我的核心数据堆栈配置了一个sqlite数据库,这是使用CoreData创建应用程序时配置的标准方式

1 个答案:

答案 0 :(得分:1)

一个原因是您在每次迭代中保存托管对象上下文,这是昂贵且不需要的。在插入最后一个项目后保存。