使用 UUID 的现代核心数据性能

Modern Core Data Performance with UUID

我有一个核心数据应用程序:

每个实体都有一个 uuidKey 字符串属性,其中包含从在线数据库导入的 UUID 字符串。

我正在尝试 运行 在 iPhone 5S 上运行该应用程序。插入对象相对较快,但查找和 link建立关系比预期的要长。

let debugTime = NSDate()
let thisRequest = NSFetchRequest(entityName: "Ledgers")
let keyLeft = NSExpression(forKeyPath: "uuidKey")
let keyRight = NSExpression(forConstantValue: ledgerKey)
let keyPredicate = NSComparisonPredicate(leftExpression: keyLeft, rightExpression: keyRight, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions.allZeros)
thisRequest.predicate = keyPredicate
thisRequest.fetchBatchSize = 1
thisRequest.fetchLimit = 1
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to create thisRequest.")
var keyError: NSError? = nil
if let keyArray = self.managedObjectContext!.executeFetchRequest(thisRequest, error: &keyError) {
    if keyArray.isEmpty {
        myLedger = nil
    } else {
        if let thisLedger = keyArray[0] as? Ledgers {
            println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to find thisLedger.")
            myLedger = thisLedger
        } else {
            myLedger = nil
        }
    }
}
println("DEBUG COMMENT: \(debugTime.timeIntervalSinceNow) time to link myLedger.")

我得到这样的记录时间:

DEBUG COMMENT: -9.20295715332031e-05 time to create thisRequest.
DEBUG COMMENT: -0.174275994300842 time to find thisLedger.
DEBUG COMMENT: -0.174659013748169 time to link myLedger.
DEBUG COMMENT: -0.00464397668838501 time to find and link myAccount.

0.09​​2 毫秒创建 NSFetchRequest 就可以了。 174 毫秒找到账本?当有 24k 分类帐时在索引 UUID 字符串上?!?我什么时候需要 link 这到 57k 期刊?

越快越好。当有 549 个帐户时,需要 4 毫秒才能找到 link myAccount,这有点令人失望,但可以接受。对于 Ledger 搜索,我预计大约需要 25-50 毫秒,而不是 174!

我运行在它自己的核心数据存储和上​​下文中使用它:

    // Initialize the persistent store coordinator for the sync session.
    let url = appDel.applicationDocumentsDirectory.URLByAppendingPathComponent("FoodyCoreModel.sqlite")
    self.syncStore = NSPersistentStoreCoordinator(managedObjectModel: appDel.managedObjectModel)
    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."
    let storeOptions: [NSObject: AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
    self.syncStore.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: storeOptions, error: &error)

    // Initialize the managed object contextfor the sync session
    self.syncContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
    self.syncContext.persistentStoreCoordinator = self.syncStore
    let nmp = NSMergePolicy(mergeType: NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType)
    self.syncContext.mergePolicy = nmp

iPhone 5S 的这种性能是否合理?我在这里阅读了很多关于 Core Data 性能的问题,但其中很多都是几年前的事了。我希望 iOS 8 和更新的设备会明显更快。我不是在尝试进行 MATCHES 或 CONTAINS 搜索,只是在索引文本字段上进行 EQUALS!

我已阅读 Core Data Performance Guide。是我遗漏了什么还是我对移动设备的期望太高了?

您的代码最有可能变慢的原因是您一次获取 Ledger 个实例,而您说其中有 24,000 个。无论如何,这将是一个主要瓶颈。提取是一项相对昂贵的操作,无论您是否在谓词中使用字符串 ID,因此您的代码将花费大部分时间进行提取。

您应该分批提取而不是一次提取一个。将 50 或 100 个左右的 uuidKey 值收集到一个数组中,并使用像 "uuidKey in %@" 这样的谓词格式,并将数组作为替换变量。处理该批次,并重复直到完成。

有关如何高效导入数据的更多详细信息,请参阅 Apple 的 "Efficiently Importing Data" 指南,尤其是名为 "Implementing Find-or-Create Efficiently" 的部分。

顺便说一句,像这样使用 println 是衡量性能的一种非常糟糕的方法。使用仪器。它会以更少的开销为您提供更多详细信息,并且不会弄乱您的代码,并将帮助您准确确定瓶颈所在。