我有将近7K个项目存储在称为Verse的关系中。我还有一个名为Translation的关系,该关系需要通过JSON文件中的一个调用来加载7K相关项目。
这是我的代码:
let container = getContainer()
container.performBackgroundTask() { (context) in
autoreleasepool {
for row in translations{
let t = Translation(context: context)
t.text = (row["text"]! as? String)!
t.lang = (row["lang"]! as? String)!
t.contentType = "Verse"
t.verse = VerseDao.findById(row["verse_id"] as! Int16, context: context)
// this needs to make a call to the database to retrieve the approparite Verse instance.
}
}
do {
try context.save()
} catch {
fatalError("Failure to save context: \(error)")
}
context.reset()
}
findById方法的代码。
static func findById(_ id: Int16, context: NSManagedObjectContext) -> Verse{
let fetchRequest: NSFetchRequest<Verse>
fetchRequest = Verse.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "verseId == %@", id)
fetchRequest.includesPropertyValues = false
fetchRequest.fetchLimit = 1
do {
let results =
try context.fetch(fetchRequest)
return results[0]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
return Verse()
}
}
在我添加VerseDao.findById
之前,此方法可以正常工作,这使整个过程真的很慢,因为它必须向Coredata数据库请求每个对象。
我通过限制获取的属性的数量并使用NSFetchedResultsController进行数据获取来做所有我想做的事,但是没有运气。
我想知道是否有任何更有效的方式插入子记录?谢谢。
答案 0 :(得分:0)
假设您的商店类型为持久性商店类型为sqlite(NSSQLiteStoreType):
首先要检查的是Verse对象的 verseId 属性是否具有Core Data fetch索引。有关获取索引的一些介绍性链接,请参见this stack overflow answer。
否则,VerseDao.findById函数中的访存可能每次都会扫描整个数据库表。
要查看索引是否正常工作,可以检查通过在Xcode方案的启动参数中添加-com.apple.CoreData.SQLDebug 1
所生成的SQL查询。
其他改进:
NSManagedObjectContext.fetch
或NSFetchRequest.execute
(等效)代替NSFetchedResultsController。 NSFetchedResultsController通常用于将结果绑定到UI。在这种情况下,使用它只会增加开销。fetchRequest.propertiesToFetch
,而是设置fetchRequest.includesPropertyValues = false
。这将避免获取不需要为与Translation对象建立关系的Verse对象属性值。