在CoreData中插入子记录很慢

时间:2018-07-18 11:02:35

标签: swift performance core-data relationship

我有将近7K个项目存储在称为Verse的关系中。我还有一个名为Translation的关系,该关系需要通过JSON文件中的一个调用来加载7K相关项目。

Verse has a one to many relationship to Translation

这是我的代码:

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进行数据获取来做所有我想做的事,但是没有运气。

我想知道是否有任何更有效的方式插入子记录?谢谢。

1 个答案:

答案 0 :(得分:0)

假设您的商店类型为持久性商店类型为sqlite(NSSQLiteStoreType):

首先要检查的是Verse对象的 verseId 属性是否具有Core Data fetch索引。有关获取索引的一些介绍性链接,请参见this stack overflow answer。 否则,VerseDao.findById函数中的访存可能每次都会扫描整个数据库表。 要查看索引是否正常工作,可以检查通过在Xcode方案的启动参数中添加-com.apple.CoreData.SQLDebug 1所生成的SQL查询。

其他改进:

  • 使用NSManagedObjectContext.fetchNSFetchRequest.execute(等效)代替NSFetchedResultsController。 NSFetchedResultsController通常用于将结果绑定到UI。在这种情况下,使用它只会增加开销。
  • 不设置fetchRequest.propertiesToFetch,而是设置fetchRequest.includesPropertyValues = false。这将避免获取不需要为与Translation对象建立关系的Verse对象属性值。
  • 不要在获取请求中指定sortDescriptor,这只会使查询复杂化