在不影响应用程序性能的情况下,从核心数据中执行对象级联删除的有效方法是什么



我们应用程序中的数据库由嵌套多层的对象组成。由于体系结构的原因,我们现在不可能从中迁移出去。

每天都有高百分比的数据过期。随着数据库规模的增长,我们的应用程序性能会下降。

因此,我们需要找到一种有效的方法来保持数据库的小型化(至少在本版本中),我们正在考虑以下方法之一:

  1. 在applicationWillResignActive期间,删除NSManagedObjects,方法是在根级别迭代所有对象,对每个对象调用delete,然后允许删除级联到"多对多"对象的3层。这涉及到最后的一个上下文保存,它将所有这些内容提交给DB。这通常需要10-20秒(在iPhone 4上)才能删除对象,Springboard会在10秒内终止该过程。这样做的一个主要缺点是,如果上下文保存没有在10秒超时之前完成,则不会删除任何内容,并且每次用户运行应用程序时,DB都会继续增长。

  2. 删除didFinishLaunchingWithOptions或应用程序DidBecomeActive内或应用程序WillResignActive内的整个sqlite文件。这迫使我们弹出到应用程序的视图控制器堆栈的根,以避免试图显示已删除的数据。这样做的最大缺点是,在用户下次启动应用程序时可以做任何事情之前,应用程序必须下载并解析数据几秒钟。

  3. 在用户按下主页或电源按钮后,使用beginBackgroundTaskWithExpirationHandler删除DB对象。与此相关的未知因素让它变得可怕。有人这样做(成功)吗?

  4. 在应用程序运行时增量删除较小的对象组。这会增加设备上的负载,从而破坏表视图的平滑度,使其抖动。API调用在删除旧对象的同时已经解析的数据量在这里似乎不切实际。

任何关于删除核心数据中对象的最佳实践的想法都将不胜感激!

橙色80,

您应该在从-applicationDidEnterBackground:中启动的后台队列中执行级联删除。为了避免被终止,您必须使用后台任务ID。

我在频繁搅动的实例CD应用程序中使用了这种策略。总的来说,使用这种策略,用户将永远不会看到删除。

Andrew

我遇到了这样的情况,我没有时间清理数据。

我解决了将一些关键实体标记为已删除(实体属性),并在以后将其删除(并级联)的问题。您不必标记每个已删除的实体,只需标记那些有意义的实体即可允许延迟删除,这样UI就可以很容易地知道是否有任何已标记的实体将被删除。听起来很难,但如果你的数据模型足够干净,那就不应该了。

当你的应用程序重新启动时,你要么删除实体并级联-如果这不能结束,你只会在可能的情况下重新启动删除-要么首先迭代并标记所有可删除的实体,可能会"一个接一个"地删除它们。这可以在后台完成,而不会扰乱UI(因为UI知道可删除实体)。如果您在执行此操作时遇到性能问题,则可以非常容易地增量处理删除。

"以后标记并删除"策略对我来说效果很好。

您可能需要考虑将选项1与标记某些实体以进行删除相结合。这样,即使在应用程序退出时删除没有完成,在启动时(假设你的应用程序启动还没有花一些时间),你也可以删除标记的实体(比如几秒钟),然后在后台进行"轻度"删除,比如在没有用户交互(没有移动表视图)的情况下。当然,这会增加一些启动应用程序的时间,但考虑到你的情况,我认为这可能是一个可行的选择。

此外,我希望您通过核心数据执行批加载,并且只在需要时将对象加载到内存中。

很快重读了你的问题,我只是有了另一个想法。。。按照#2的思路……为什么不尝试将过时的数据迁移到一个单独的文件中,然后当用户退出应用程序时,只删除该文件?迁移这些对象肯定会有开销,但它可能会提供更流畅的用户体验。

最新更新