【问题标题】: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,但没有结果。我尝试了更多的方法,一些非常慢,另一些则非常消耗记忆。

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

提前致谢

【问题讨论】:

    标签: ios objective-c core-data foreign-key-relationship nsfetchrequest


    【解决方案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];
      

      【讨论】:

      • 感谢您的回复!我的实现与您描述的非常相似,但我会将另一个答案标记为正确,因为是相同的想法,他稍后回答。但无论如何,很好的答案!实际上我需要每周做两次左右,但至少我现在没有收到内存警告。
      猜你喜欢
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      相关资源
      最近更新 更多