Core数据子上下文不预取关系 [英] Core Data child contexts not prefetching relationships

查看:222
本文介绍了Core数据子上下文不预取关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中激活了Core Data调试器 -com.apple.CoreData.SQLDebug 1 ,并为名为Category的实体获得了以下结果图片:



主上下文中的FetchRequest

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

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

(结果中的类别*类别){

NSLog(@%@,category.image.width);
}

控制台日志不会显示任何故障 -



<$ p

$ p> 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];

(结果中的类别*类别){

NSLog(@%@,category.image.width);
}
}];

在这种情况下,控制台显示Core Data为每个映像执行故障(其中4个)。

解决方案

实验:



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

  ************************ ******** 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:绑定的intarray值。
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获取时间:0.0006s
CoreData:注释:总获取执行时间:4行为0.0010s。
CoreData:注释:使用键'image'预取。有4行。
CoreData:annotation:总获取执行时间:0.0035s为4行。

********************************背景********* *****************************

CoreData:sql:SELECT 0,t0.Z_PK,t0。 Z_OPT,t0.ZTIMESTAMP,t0.ZTITLE,t0.ZIMAGE从ZCATEGORY t0
CoreData:注释:sql连接获取时间:0.0003s
CoreData:注释:总获取执行时间:0.0005s为4行。



分析:



a href =https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/#//apple_ref/occ/instp/NSFetchRequest/relationshipKeyPathsForPrefetching =nofollow>文档的 NSFetchRequest ,解释了提供预取以解决具体的性能挑战。它描述如下(我强调):


预取允许Core Data在单个获取(每个实体)中获取相关对象,比随着他们的故障跳闸而对每个单独的记录随后访问存储器。例如,给定一个与部门实体具有关系的Employee实体,如果您提取所有员工,则每次打印出他们的名字和他们所属部门的名称,可能是因为每个单独的部门对象(有关更多详细信息,请参阅核心数据编程指南中的核心数据性能)。这可以表示显着的开销。


您可以 通过预先抓取部门关系来避免这种情况因为这不是必要的 设备,以提高性能。这将解释为什么它不在后台线程上实现:讨论中描述的性能问题似乎表明涉及UI更新的典型情况。在我看来,这澄清了这个功能的意图。



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


I activated the Core Data debugger -com.apple.CoreData.SQLDebug 1 in my app scheme and got the following results for an entity called Category with a relationship entity called Image:

FetchRequest on the main context:

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);
}

The console log shows no faults being fulfilled - the expected behavior since the image relationship was set for prefetching.

The same request on a child context:

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);
        }
    }];

In this case, the console shows Core Data fulfilling faults for each image (4 of them). Is this a bug, expected behavior or am I missing something please?

解决方案

Experiment:

I have replicated your scenario in a test app and come to the same conclusion: the prefetching is not happening in the background thread. Log:

******************************** 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.

Analysis:

According to the documentation of NSFetchRequest, it is explained that the prefetching is offered to address specific performance challenges. It is described as follows (my emphasis):

Prefetching allows Core Data to obtain related objects in a single fetch (per entity), rather than incurring subsequent access to the store for each individual record as their faults are tripped. For example, given an Employee entity with a relationship to a Department entity, if you fetch all the employees then for each print out their name and the name of the department to which they belong, it may be that a fault has to be fired for each individual Department object (for more details, see Core Data Performance in Core Data Programming Guide). This can represent a significant overhead. You could avoid this by prefetching the department relationship in the Employee fetch...

From the wording it follows that this is not a necessary device to improve performance. This would explain why it is not implemented on a background thread: the performance issue described in the discussion seems to indicate a typical scenario involving UI updates. To my mind, this clarifies the intent of this feature.

If you are already on a background thread, this kind of performance tuning is surely less critical and the usual faulting mechanism can handle the necessary optimization adequately. The property relationshipKeyPathsForPrefetching will thus revert to its default value, an empty array.

这篇关于Core数据子上下文不预取关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆