使用NSPredcates过滤获取核心数据所花费的时间~WEIRD



因此,我正试图从核心数据中提取大约2000个对象,并试图找出提取它们的最快方法。

没有NSPredcates:

当我添加这个块(如下)时,if语句占用了执行总时间的90%,这是可以理解的,所以我对它进行了注释。

Block {
    NSError *error;
    NSManagedObjectContext *context =  <#Get the context#>;
    // The IF block
/*   if (![context save:&error])
    {
        NSLog(@"error %@", error);
    }
*/
       // The block above takes 90% of the total time of fetch
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *theEntity = [NSEntityDescription 
                                  entityForName:@"EntityName" inManagedObjectContext:context];
    [fetchRequest setEntity:theEntity];
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];    
    }

使用NSPredcates:

我将谓词设置为

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"handle == %@",handle];

并执行与Block() 中所示相同的提取

可以看出,总的时间正好相反——如果我使用IF BLOCK~6秒,它会快90%左右。

否则,如果该块被注释,则获取时间为LOT-3分钟。只有在为fetchRequest设置predicate时才会发生这种情况。

有人能解释一下吗?

也就是说,

 /*
 Save + straight fetch = slow, due to saving. 
 Straight fetch - pretty fast. 
 Predicate fetch, slow. 
 Save + predicate fetch, much faster? 
 */

(猜测,希望能接受教育)保存后,上下文可以直接对数据库执行预测提取,因为它知道没有对象的更改尚未写入数据库。如果没有保存,它必须针对DB以及任何可能有未保存更改的现存对象进行提取。

当我试图了解核心数据的内部工作时,使用以下参数打开SQL调试会有所帮助:

    -com.apple.CoreData.SQLDebug 1

这将打印出所有正在执行的SQL语句,因此您可以真正看到差异。也有可能(只是一种理论),在保存之后,持久存储(或者可能只是索引)仍在缓存中,从而使索引(谓词)获取速度更快。

无论如何,SQL调试将向您显示执行了哪些语句以及何时执行,这可能会导致对模型中的索引进行一些优化。

效率的提高与执行获取的方式无关。

延迟的原因是您正在保存在if块中。这是一项相当昂贵的手术。如果你做2000次,可能需要几秒钟甚至更长时间。

当您从持久存储中获取实体时,只有当您要修改这些实体时,才有意义进行保存。即使这样,你也会尽量把你的电话存到最低限度。

最新更新