我应该多久保存到 Core Data?

Posted

技术标签:

【中文标题】我应该多久保存到 Core Data?【英文标题】:How often should I save to Core Data? 【发布时间】:2010-06-21 13:46:50 【问题描述】:

我正在开发一个由 Core Data 支持的应用程序。 现在,当我在上下文中添加或删除实体时,我正在保存对象上下文。 我怕会影响性能,所以我在考虑延迟保存。 事实上,我可以一直推迟到应用程序终止。 仅在应用程序即将关闭时才保存数据是否太冒险?我应该多久调用一次对象上下文的保存?

我正在考虑让一个单独的线程处理保存:它将等待一个信号量。每次应用程序的任何部分调用 helper/util 方法来保存核心数据时,它都会减少信号量。当它降至零时,“保存线程”将执行一次保存,并将信号量增加到 a,例如 5,然后再次休眠。

有什么好的推荐吗? 谢谢!

【问题讨论】:

【参考方案1】:

您应该经常保存。保存操作的实际性能与您使用的持久存储类型有很大关系。由于二进制和 XML 存储是原子的,因此每次保存时都需要将它们完全重写到磁盘上。随着对象图的增长,这确实会减慢您的应用程序。另一方面,SQLite 存储更容易以增量方式写入。因此,虽然会在您保存的对象之上和之外编写一些内容,但开销远低于原子存储类型。无论整体对象图大小如何,仅影响少数对象的保存总是很快。

也就是说,如果您在循环中导入数据,我会等到整个操作结束后再保存,而不是在每次迭代时保存。您的主要目标应该是防止数据丢失。 (我发现用户不太关心这个!)性能应该紧随其后。您可能需要做一些工作来平衡节省频率与性能之间的关系,但您在上面概述的解决方案似乎有些矫枉过正,除非您已经确定了一个特定且重要的性能问题。

【讨论】:

感谢您的快速回答。我的对象并不大,但对象有点复杂。底层存储是 SQLite,所以正如你所说,应该没问题。我最近遇到了一个额外的问题:我在上下文中创建了一个实体对象并保存它。很快,如果我删除该实体(稍后使用 FetchedResultsController 检索),我会收到与内部一致性有关的错误。我认为是因为上下文没有更新内存中的对象图? 我想补充一点,你想让你的实际保存频率成为一个变量或#define,这样一旦你在测试中,你就可以微调你的保存频率并在 Instruments 中观察结果。 【参考方案2】:

在其他答案中未提及的一个问题是,您的解决方案涉及使用后台线程,不应在另一个线程中使用的托管对象上下文上运行。通常你会为后台线程创建一个新的 MOC,但如果你保存到不同的/未修改的后台 MOC,那会破坏保存的目的。

所以你的问题的几个答案:

    你需要回调你原来的线程来保存 MOC 正如当前接受的答案表明,除非测量性能问题,否则整个计数器可能无法满足您的需求。 如果测量了性能问题,您可以采用简单的限制技术,将限制设置为每 10 秒保存 1 次。存储您上次保存的日期。调用保存函数时,请始终确保当前时间距上次保存时间 > 10 秒,否则请提前返回。

你真的想尽可能多地立即存钱,所以至少我的建议是节流,而不是随意设置任何计时器或倒计时。

【讨论】:

【参考方案3】:

我认为最好的方法是在每个对象之后保存。如果发生诸如突然崩溃之类的事情,则不会丢失任何东西。

一些性能增强,如果你添加很多对象是为了批处理。将所有对象添加到上下文而不是保存。例如,如果您在循环中添加很多对象,这很好。你的想法是类似的,但是保存之间可能有很长的时间,程序可能会崩溃。

我不认为添加单个对象会成为性能问题。您的对象有多大,它们是否包含大量数据?

【讨论】:

每次崩溃后保存?我认为这是一个错字。当然,如果用户通过创建对象来指示保存,则用户无法以足够快的速度创建对象以减慢应用程序的速度。如果您认为它会减慢您的应用程序的速度,从而冒着节省不足的风险。请提供证据,我所有的基准测试都是可以接受的。 在用户创建后保存是有意义的。但是,在处理数千件事情的循环的每一轮中进行保存对于闪存存储来说是缓慢且不利的。在批处理作业期间每 10 秒保存一次,加上完成后,是我的典型方法。

以上是关于我应该多久保存到 Core Data?的主要内容,如果未能解决你的问题,请参考以下文章

我应该多久保存一次文件?

用户更新软件后如何保存Core Data?

Core Data iPhone 在插入 50k 记录时,我应该多久调用一次 [managedObjectContext save:&error]?

将 UIImage 保存到 Core Data 时出错

将对象数组保存到 Core Data

使用 RSAPI 将 JSON 保存到 Core Data