问题描述
我正在开发一个可定期从服务器下载数据的应用程序.如果需要更新数据,我将使用类似以下的方法来更新记录或插入不存在的新记录.
I am developing an app that downloads data from a server regularly. If the data needs updated, I use something like to following to update the records or insert new records if they don't exist.
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Trip")
for csvTrip in csvTrips {
var trip: NSManagedObject!
let tripId = Int(csvTrip[0])!
fetchRequest.predicate = NSPredicate(format: "id = %d", tripId)
if (context.count(for: fetch) == 0) {
trip = NSEntityDescription.insertNewObject(forEntityName: "Trip", into: context)
trip.setValue(tripId, forKey: "id")
} else {
tripObject = (context.fetch(fetch) as! [NSManagedObject])[0]
}
// Set other properties
}
检查该实体是否已存在于每个循环中,这使其比不检查就插入它们慢了大约100倍,这对于成千上万个实体来说是一个大问题.我尝试过先获取所有实体,但仍然必须遍历每个实体,并将id添加到数组或其他内容中,这并不快.我知道核心数据与MySQL不同,但是我很难相信没有类似于INSERT ... ON DUPLICATE KEY UPDATE的功能,这在MYSQL中非常快.我想念什么吗?
Checking if the entity already exists in each loop makes it about 100 times slower than just inserting them without checking, which becomes a big problem with more than a few thousand entities. I've tried fetching all the entities first, but I still have to loop through each one and add the id to an array or something, which isn't much faster. I know core data isn't the same as MySQL, but it's hard for me to believe that there isn't a feature similar to INSERT ... ON DUPLICATE KEY UPDATE, which is extremely fast in MYSQL. Am I missing something?
推荐答案
如果获取甚至数千个实体并将id加载到 Set
中的时间特别长,我会感到惊讶.
I would be surprised if fetching even a few thousand entities and loading the ids into a Set
took a particularly long time.
您可以使用类似的内容:
You could use something like:
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Trip")
fetchRequest.resultType = .dictionaryResultType
fetchRequest.propertiesToFetch = ["id"]
do {
if let results = try self.moc.fetch(fetchRequest) as? [[String:Any]] {
let idSet = Set<Int32>(results.flatMap({ (dict) -> Int32? in
return dict["id"] as? Int32
}))
}
} catch {
print("Error reading trips")
}
现在,您可以轻松检查给定ID是否为新ID,并在需要时插入新行程:
Now you can easily check if a given id is new or not and insert a new trip if required:
for csvTrip in csvTrips {
if let tripId = Int(csvTrip[0]) {
if !idSet.contains(tripId) {
trip = NSEntityDescription.insertNewObject(forEntityName: "Trip", into: context)
trip.setValue(tripId, forKey: "id")
}
}
}
在我的测试中,这花费了1.35秒,将320,000个旅行ID加载到集合中,并花费了0.08秒创建了10,000个新旅行,同时检查了旅行ID是否包含在集合中.
In my test, this took 1.35 seconds to load 320,000 trips ids into a set and 0.08s to create 10,000 new trips whilst checking to see if the trip id was contained in the set.
这篇关于用Core Data插入/更新记录的最有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!