迁移大型 Core Data 数据库崩溃

Posted

技术标签:

【中文标题】迁移大型 Core Data 数据库崩溃【英文标题】:Migrating large Core Data database crash 【发布时间】:2013-02-15 16:50:35 【问题描述】:

我有一个将产品存储在核心数据文件中的应用程序。这些产品包括作为“可转换”数据的图像。 现在我尝试使用轻量级迁移添加一些属性。当我用一个小型数据库对其进行测试时,它运行良好,但是当我使用一个接近 500 MB 的非常大的数据库时,应用程序通常会因为内存不足而崩溃。有人知道如何解决这个问题吗?

提前致谢!

【问题讨论】:

我没有使用过核心数据,但我的理解是它不适合大型数据库,其他一些数据库实现可能是一个更好的主意。也许是 mysql @Robert - 完全不正确。在某些情况下它不适合,但尺寸不是其中之一。此外,CoreData 不是数据库。 HackingOtter 可能需要考虑仅存储图像的 URL,并将图像保存在 Documents 目录中。 啊,好的。不知道我从哪里得到这个想法。 【参考方案1】:

您必须使用其他迁移选项之一。自动轻量级迁移过程使用起来真的很方便。但它有一个缺点,即一次将整个数据存储加载到内存中。两份,真的,一份是迁移前的,一份是迁移后的。

首先,是否可以重新创建或重新下载这些数据?如果是这样,您也许可以使用从旧版本到新版本的自定义映射模型。使用自定义映射模型,您可以指示某些属性不会被迁移,从而通过丢弃该数据来减少内存问题。然后在迁移完成后,重新创建或重新下载该数据。

如果不是这样... Apple 建议使用多个映射模型的多通道技术。如果您有多种实体类型会影响大型数据存储大小,那么它可能会有所帮助。基本上,您最终会在不同的过程中迁移不同的实体类型,因此您可以避免一次加载所有内容的开销。

如果 that 不是这种情况(例如,膨胀全部来自同一实体类型的实例),那么是时候编写您自己的自定义迁移代码了。这将涉及设置两个 Core Data 堆栈,一个使用现有数据,一个使用新模型。运行现有数据存储,在新存储中创建新对象。如果您分批执行此操作,您将能够控制内存。一般的做法是:

    在新模型中创建新实例并复制仅属性。您还不能设置关系,因为新数据存储中可能不存在相关对象。保留一个从旧存储到新存储的可变字典映射NSManagedObjectIDs,以供下一步使用。为了保持低内存使用: 创建目标存储对象后,立即使用refreshObject:mergeChangesNO 作为第二个参数释放源对象的内存。 每 10 个实例(或 50 个,或其他)保存目标托管对象上下文的更改,然后 reset 它。间隔是一种平衡行为 - 太频繁会不必要地放慢速度,太少会增加内存使用量。 在目标商店中设置关系的第二遍。对于每个源对象, 使用您创建的对象 ID 映射查找相应的目标对象 遍历源对象的关系。对于每一个,找到对应的目标对象,同样使用对象 ID 映射。 根据结果设置目标对象的关系。

当您使用它时考虑一下为什么您的数据存储如此之大。您是否在数据存储中存储了一堆二进制数据块?如果是这样,请确保您在新模型中使用“允许外部存储”选项。

【讨论】:

h感谢您的回答。有人知道这方面的好教程吗? 这家伙描述了一部分,但他没有要处理的关系:hamishrickerby.com/2012/06/04/… 对于我们这些不幸地意识到最后一个策略是唯一合适的策略的人来说,这是一个很好的洞察力。但是,我想建议在源实体上调用 [srcContext refreshObject:srcEntity mergeChanges:NO] 只能解决一半的内存问题。每个目标对象都不会有尽可能多的内存浮动吗? 有点,是的,但这就是批量进行的地方。定期保存更​​改并重置目标上下文。这会限制内存增长,因为您会定期清除它。

以上是关于迁移大型 Core Data 数据库崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Core Data 的推断映射模型创建(轻量级迁移)崩溃。线程问题?

在迁移时从 iCloud 迁移到本地商店崩溃的应用程序“对象不能为零” - 使用 Core Data

在 Core Data 迁移后插入数据

Core Data迁移后如何保持数据有序?

考虑使用 Core Data 轻量级迁移的多个数据模型版本

当涉及多个设备时,Core Data iCloud 迁移“丢失”数据