因此,我正试图从核心数据中提取大约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次,可能需要几秒钟甚至更长时间。
当您从持久存储中获取实体时,只有当您要修改这些实体时,才有意义进行保存。即使这样,你也会尽量把你的电话存到最低限度。