核心数据子环境不预取关系

Run*_*oop 10 core-data ios

我-com.apple.CoreData.SQLDebug 1在我的应用程序方案中激活了Core Data调试器,并获得了一个名为Category的实体的以下结果,其中包含一个名为Image的关系实体:

主要上下文中的FetchRequest:

NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"Category"];
fr.relationshipKeyPathsForPrefetching = @[@"image"];

NSArray *results = [self.mainContext executeFetchRequest:fr error:nil];

for (Category *category in results) {

    NSLog(@"%@", category.image.width);
}
Run Code Online (Sandbox Code Playgroud)

控制台日志显示未满足任何错误 - 自映像关系设置为预取以来的预期行为.

对子上下文的相同请求:

NSManagedObjectContext *privateMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[privateMOC setParentContext:self.mainContext];

[privateMOC performBlock:^{

        NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"Category"];
        fr.relationshipKeyPathsForPrefetching = @[@"image"];

        NSArray *results = [privateMOC executeFetchRequest:fr error:nil];

        for (Category *category in results) {

            NSLog(@"%@",category.image.width);
        }
    }];
Run Code Online (Sandbox Code Playgroud)

在这种情况下,控制台显示Core Data为每个图像(其中4个)执行故障.这是一个错误,预期的行为还是我错过了什么?

Mun*_*ndi 5

实验:

我已经在测试应用程序中复制了您的场景并得出了相同的结论:预取不是在后台线程中发生的。日志:

******************************** FOREGROUND **************************************

CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZTIMESTAMP, t0.ZTITLE, t0.ZIMAGE FROM ZCATEGORY t0 
CoreData: annotation: sql connection fetch time: 0.0004s
CoreData: annotation: Bound intarray values.
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZURL FROM ZIMAGE t0 WHERE  t0.Z_PK IN (SELECT * FROM _Z_intarray0)  
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0010s for 4 rows.
CoreData: annotation: Prefetching with key 'image'.  Got 4 rows.
CoreData: annotation: total fetch execution time: 0.0035s for 4 rows.

******************************** BACKGROUND **************************************

CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZTIMESTAMP, t0.ZTITLE, t0.ZIMAGE FROM ZCATEGORY t0 
CoreData: annotation: sql connection fetch time: 0.0003s
CoreData: annotation: total fetch execution time: 0.0005s for 4 rows.
Run Code Online (Sandbox Code Playgroud)

分析:

根据该文件的NSFetchRequest,它解释说,预取是提供给地址特定的性能挑战。描述如下(我的重点):

预取允许 Core Data 在单个 fetch(每个实体)中获取相关对象,而不是在它们的故障被触发时导致对每个单独记录的后续访问。例如,给定一个与 Department 实体有关系的 Employee 实体,如果您获取所有员工,然后为每个员工打印出他们的姓名和他们所属的部门的名称,则可能必须为以下原因触发故障每个单独的部门对象(有关更多详细信息,请参阅核心数据编程指南中的核心数据性能)。这可能代表显着的开销。您可以通过在 Employee fetch 中预取部门关系来避免这种情况...

从措辞可以看出,这不是提高性能的必要手段。这将解释为什么它不在后台线程上实现:讨论中描述的性能问题似乎表明涉及 UI 更新的典型场景。在我看来,这阐明了此功能的意图。

如果您已经在后台线程中,那么这种性能调优肯定不那么重要,通常的故障机制可以充分处理必要的优化。relationshipKeyPathsForPrefetching因此,该属性将恢复为其默认值,即一个空数组。

  • 我有同样的问题。与单个预取相比,在后台线程上触发数千个故障并不快,它很慢并且需要永远。所以我不认为这可以解释为任何有意的优化。 (2认同)