核心数据量大

时间:2016-09-27 14:35:34

标签: ios sqlite core-data

每次应用程序启动时,我都会从Web服务中检索25000条记录。 在初始化阶段,我想将所有这些项目保存到核心数据中。 此操作的时间约为20分钟。 是否可以更快速地将所有项目保存到核心数据中? 使用sqlite工具将它们保存到sqlite数据库然后实例化核心数据是个好主意?

编辑:

保存到核心数据20分钟。

func storeDevices(_ dataStack: DATAStack,value: [JSON]) -> Bool
{
    dataStack.performInNewBackgroundContext { backgroundContext in
    let entityDevices = NSEntityDescription.entity(forEntityName: "Devices", in: backgroundContext)

    for item in value
    {
        if !item["event_id"].stringValue.isEmpty
        {
            let id = item["id"].stringValue
            let predicate = NSPredicate(format: "%K == %@", "id", id)
            let typesFetchRequest = NSFetchRequest<Devices>(entityName: "Devices")
            typesFetchRequest.predicate = predicate
            do {
                let fetchedTypesResults = try backgroundContext.fetch(typesFetchRequest) as! [Devices]
                if (fetchedTypesResults.count > 0)
                {
                    let typeUpdate = fetchedTypesResults[0]
                    switch item["is_Deleted"].stringValue
                    {
                    case "true":
                        typeUpdate.setValue(true, forKey: "deletedStatus")
                    case "false":
                        typeUpdate.setValue(false, forKey: "deletedStatus")
                    default:
                        typeUpdate.setValue(false, forKey: "deletedStatus")
                    }

                    if let intVersion = Int(item["last_modified"].stringValue) {
                        typeUpdate.setValue(intVersion, forKey: "lastModified")
                    } else {
                        typeUpdate.setValue(NSNumber(value: 0 as Int32), forKey: "lastModified")
                    }

                    typeUpdate.setValue(NSNumber(value: 0 as Int32), forKey: "syncStatus")

                    typeUpdate.setValue(item["deviceUUID"].stringValue, forKey: "deviceUUID")
                    typeUpdate.setValue(item["deviceLocation"].stringValue, forKey: "deviceLocation")

                    let event_id = item["event_id"].stringValue
                    if !event_id.isEmpty
                    {

                        let predicate = NSPredicate(format: "%K == %@", "id", event_id)
                        let typesFetchRequest = NSFetchRequest<Events>(entityName: "Events")
                        typesFetchRequest.predicate = predicate

                        do {
                            let fetchedTypesResults = try backgroundContext.fetch(typesFetchRequest) as! [Events]
                            if (fetchedTypesResults.count > 0)
                            {
                                typeUpdate.setValue(fetchedTypesResults[0], forKey: "event")
                            }
                            else
                            {
                                continue
                            }
                        } catch {
                            let saveError = error as NSError
                            print("Failed to fetch events in Devices: \(saveError)")
                        }
                    }


                    continue
                }

            } catch {
                fatalError("Failed to fetch devices: \(error)")
            }

            let deviceNewElement = Devices(entity: entityDevices!, insertInto: backgroundContext)
            deviceNewElement.id = id
            switch item["is_Deleted"].stringValue
            {
            case "true":
                deviceNewElement.deletedStatus = true
            case "false":
                deviceNewElement.deletedStatus = false
            default:
                deviceNewElement.deletedStatus = false
            }

            if let intVersion = Int(item["last_modified"].stringValue) {
                deviceNewElement.lastModified = intVersion as NSNumber?
            } else {
                deviceNewElement.lastModified = NSNumber(value: 0 as Int32)
            }

            deviceNewElement.deviceUUID = item["deviceUUID"].stringValue
            deviceNewElement.deviceLocation = item["deviceLocation"].stringValue

            let event_id = item["event_id"].stringValue
            if !event_id.isEmpty
            {
                let predicate = NSPredicate(format: "%K == %@", "id", event_id)
                let typesFetchRequest = NSFetchRequest<Events>(entityName: "Events")
                typesFetchRequest.predicate = predicate

                do {
                    let fetchedTypesResults = try backgroundContext.fetch(typesFetchRequest) as! [Events]
                    if (fetchedTypesResults.count > 0)
                    {
                        deviceNewElement.event = fetchedTypesResults[0]
                    }
                    else
                    {
                        continue
                    }
                } catch {
                    let saveError = error as NSError
                    print("Failed to fetch events in Devices: \(saveError)")
                }
            }

            deviceNewElement.syncStatus = NSNumber(value: 0 as Int32)
        }
    }   
        try! backgroundContext.save()
    }
    return true

}

3 个答案:

答案 0 :(得分:0)

是的,最好使用sqlite3函数进行批量插入。因为核心数据不可能这样做。

答案 1 :(得分:0)

保存25000条记录不应该花费20分钟,尝试启动多个线程和上下文并将它们保存到coredata。请分享您的示例代码,我们可以提供帮助。下面是一个示例元代码,可以节省更多时间保存到磁盘

loop and create threads for every 1000 records using dispatch_async etc
on each thread, call dispatch_enter, create a thread context taken from parent root context
loop the 1000 records of this thread and upsert (update or insert) them into the context
save the context and call dispatch_leave
Finally know that everything is saved in dispatch_notify

答案 2 :(得分:0)

您需要优化CoreData的使用方式。

处理您的数据并找出需要触摸的ManagedObjects,在循环之外预先获取这些数据。注意可能还需要预取的任何关系。你不希望故障不断发射。

现在进行所有更改。最后保存一次。

如果内存压力很大,请将数据分成几千块,并按上述方式处理。使用@autoreleasepool。