核心数据关系的性能改进

Posted

技术标签:

【中文标题】核心数据关系的性能改进【英文标题】:Performance improvement in Core Data relationship 【发布时间】:2016-01-22 11:22:45 【问题描述】:

我有两个预先填充的核心数据实体(它们有关系,以及它的逆关系)(每个大约有 50k 个寄存器),我需要建立一个关系。这几乎是1:1的关系。它们有一个共同的属性,所以如果两个属性相等,它们一定是有关系的。

我正在尝试以粗略的方式进行操作,但遇到了很多内存问题(它很快升级为内存警告)。

@autoreleasepool         
    NSFetchRequest *e2sRequest = [[NSFetchRequest alloc] initWithEntityName:@"Entity2"];
    e2sRequest.includesPropertyValues = NO;
    e2sRequest.includesSubentities = NO;
    NSArray *e2s = [self.fatherMOC executeFetchRequest:e2sRequest error:nil];

    if(e2s.count > 0) 
        NSFetchRequest *e1sRequest = [[NSFetchRequest alloc] initWithEntityName:@"Entity1"];
        e1sRequest.includesPropertyValues = NO;
        e1sRequest.includesSubentities = NO;
        NSArray *e1s = [self.fatherMOC executeFetchRequest:e1sRequest error:nil];

        for(Entity1 *e1 in e1s) 
            NSString *attributeInCommon = e1.attributeInCommon;
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"attributeInCommon = %@", attributeInCommon];
            Entity2 *e2matching = (Entity2 *)[e2s filteredArrayUsingPredicate:predicate].lastObject;
            if(e2) 
                e1.e2 = e2matching;
            
        
    

我尝试在 NSDictionary 中获取内存中的共同属性和 objectID,但没有结果。我尝试了更多的方法,一些非常慢,另一些则非常消耗记忆。

我知道我必须检查错误,我知道我可以用更少的代码行来完成它,但将其视为调试/紧急代码,所以我会修复。

提前致谢

【问题讨论】:

【参考方案1】:

您正在尝试同时加载 100000 个项目,所以难怪您有内存问题。

您需要批处理,如果您创建了一个自动释放池,有时您需要将其排空(因此它需要参与批处理)。

所以,在第一个获取请求上设置一个fetchBatchSize。然后,迭代它发现的结果,一次取fetchBatchSize 个项目。这是池应该在的位置,以便在每批之后释放它。从一批 100 个开始,看看情况如何。

然后每个批次使用谓词进行第二次查询,以限制可以与当前批次实际匹配的值集。

然后运行你的匹配逻辑。

还可以考虑使用 Instruments 中的 Core Data 工具来检查正在发生的事情、您对数据存储提出了多少请求以及这一切需要多长时间。

【讨论】:

【参考方案2】:

我认为此操作(基于充当唯一键的公共字符串属性将 50.000 个实体与 50.000 个其他实体匹配)不是您希望在用户设备上重复的操作。相反,您似乎需要一次来准备种子数据。

因此实际上不需要优化,因为时间和(在模拟器上)内存不会成为问题。

所以只需分批执行此操作,例如如下:

获取 1000 个 e1, 使用谓词获取 1000 个对应的 e2 链接 保存 耗尽内存 重复

一些提示:

要获取不同的 1.000 条记录块,请添加排序描述符并使用 fetchOffsetfetchLimit

获取记录的谓词是这样的。

NSArray *attributes = [e1Results valueForKeyPath:@"attributeInCommon"];
request.predicate = 
    [NSPredicate predicateWithFormat:@"attributeInCommon in @%", attributes];

【讨论】:

感谢您的回复!我的实现与您描述的非常相似,但我会将另一个答案标记为正确,因为是相同的想法,他稍后回答。但无论如何,很好的答案!实际上我需要每周做两次左右,但至少我现在没有收到内存警告。

以上是关于核心数据关系的性能改进的主要内容,如果未能解决你的问题,请参考以下文章

Lucene 8.0关于DocValues的改进

从属性中建立核心数据关系的最快方法是啥?

深度学习核心技术精讲100篇(五十四)-阿里文娱多模态视频分类算法中的特征改进

核心数据在获取时是不是返回对象AsFaults = NO 也有错误关系?

iOS 瓶颈:全局变量与核心数据或属性列表

使用子查询高效获取核心数据