核心数据存储器高效迁移

时间:2014-10-03 15:36:47

标签: ios objective-c iphone cocoa core-data

我目前正在为一个应用程序构建CoreData迁移,该应用程序每个实体的平均数据行数为200k / 50k。 CoreData模型中目前有15个实体。

这是我为此应用程序构建的第7次迁移,所有以前的迁移都很简单(添加1或2列样式)迁移,这些迁移没有任何问题,也不需要任何映射模型。

此迁移

与以前的迁移相比,我们正在进行的迁移相当大,并在两个现有实体之间添加了一个新实体。这需要我们构建的自定义NSEntityMigrationPolicy来映射新的实体关系。我们还有一个* .xcmappingmodel,它定义了模型6和新模型7之间的映射。

我们已经实现了我们自己的NSMigrationManager子类(根据http://www.objc.io/issue-4/core-data-migration.html + http://www.amazon.com/Core-Data-Management-Pragmatic-Programmers/dp/1937785084/ref=dp_ob_image_bk)。

问题

Apple使用NSMigrationManager的migrateStoreFromURL方法来迁移模型,但是,这似乎是为低/中数据集大小构建的,不会使内存过载。

由于以下苹果方法不会频繁地将内存转储到数据传输上,我们发现应用程序因内存过载(iPad Air / iPad 2上的@ 500-600mb)而崩溃。

[manager migrateStoreFromURL:sourceStoreURL type:type options:nil withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:type destinationOptions:nil error:error];

Apple的建议解决方案

Apple建议我们应该将* .xcmappingmodel划分为每个实体的一系列映射模型 - https://developer.apple.com/library/ios/documentation/cocoa/conceptual/CoreDataVersioning/Articles/vmCustomizing.html#//apple_ref/doc/uid/TP40004399-CH8-SW2。这将与上面的NSMigrationManager子类中定义的progressivelyMigrateURL方法巧妙地协同工作。但是,我们无法使用此方法,因为单独一个实体因单个实体的大小而导致内存过载。

我的猜测是我们需要编写自己的migrateStoreFromURL方法,但是希望尽可能接近Apple的意图。有没有人之前做过这个和/或对我们如何实现这个目标有任何想法?

2 个答案:

答案 0 :(得分:1)

简短的回答是,重度迁移对iOS不利,应该避免任何代价。它们从未被设计为在内存受限的设备上工作。

在我们讨论决议之前,先说了几句问题:

  1. 数据是否可以恢复?你能再次下载它还是这个用户数据?

  2. 您是否可以在没有旧关系的情况下解决实体之间的关系?可以重建吗?

  3. 我有一些解决方案,但它们依赖于数据,因此问题会回复给您。

    更新1

      

    数据无法恢复,无法重新下载。数据来自应用程序内一段时间内的用户活动(过去最多可达1年)。这些关系也不可重构,除非我们在失去对旧关系的访问权之前存储它们。

    好的,你所描述的是最糟糕的情况,因此也是最难的情况。幸运的是,这不是无法解决的。

    首先,重型迁移不起作用。我们必须编写代码来解决这个问题。

    第一个选项

    我首选的解决方案是执行轻量级迁移,只有添加(现在)三个实体之间的新关系,它不会删除旧关系。这种轻量级迁移将在SQLite中进行,并且非常快。

    完成迁移后,我们迭代对象并根据旧关系设置新关系。这可以作为后台进程完成,也可以在使用对象时进行分餐。这是一个商业决策。

    完成转换后,您可以根据需要执行其他迁移,以删除旧关系。此步骤不是必需的,但它确实有助于保持模型清洁。

    第二个选项

    另一个有价值的选择是导出和重新导入数据。这具有设置代码的附加价值,以便以其他平台上可读的格式备份用户的数据。将数据导出到JSON然后设置导入例程将数据与新关系一起拉入新模型中非常简单。

    第二个选项的优点是更干净,但需要更多代码以及用户活动中的“暂停”。第一个选项可以在用户甚至不知道正在进行迁移的情况下完成。

答案 1 :(得分:0)

如果我理解正确,那么你有一个实体是如此之大,以至于迁移此实体时会导致内存过载。在这种情况下,如何在几个步骤中拆分这一个实体的迁移,从而每次迁移迭代只执行一些属性?

这样您就不需要编写自己的代码,但可以从“标准”代码中受益。