【问题标题】:Core Data sqlite-wal file gets MASSIVE (>7GB) when inserting ~5000 rows插入约 5000 行时,Core Data sqlite-wal 文件会变得 MASSIVE (>7GB)
【发布时间】:2013-12-12 06:28:06
【问题描述】:

我正在将数据导入Core Data,发现保存操作很慢。使用 iOS 模拟器,我看到 sqlite-wal 文件不断增长,直到超过 7GB。

我正在导入大约 5000 条记录,其中包含大约 10 个字段。这不是很多数据。

我插入的每个对象都与其他各种对象具有一对一的关系(总共 6 个关系)。所有这些记录加起来不到 20 个字段。没有图像或任何二进制数据或任何我能看到的东西可以证明 WAL 文件的结果大小如此巨大。

我阅读了描述 wal 文件的 sqlite 文档,但我不明白这是怎么发生的。源数据不超过 50 MB。

我的应用是多线程的。 我在执行导入的后台线程中创建了一个托管对象上下文(创建并保存核心数据对象)。

这里没有写代码,有没有人遇到过这种情况?任何人都对我应该检查什么有想法。代码不是超级简单,所有部分都需要时间在这里输入,所以让我们从一般的想法开始。

我会感谢任何让我朝着正确方向前进的人。

额外信息:

  • 我已经为上下文禁用了撤消管理器,因为我不需要它(我认为它在 iOS 上默认为 nil,但我明确将其设置为 nil)。
  • 我只在整个循环完成并且所有托管对象都在 ram 中后才调用 save(顺便说一下,ram 上升到 100 MB)。
  • 核心数据对象的循环和创建只需要5秒左右。在写入 awl 文件时,保存需要将近 3 分钟。

【问题讨论】:

  • 你会提供任何代码吗?
  • 如果需要我会的。但我真的首先在寻找想法。当我使用包装类和多个线程时,调用了很多代码。该行为似乎与 sqlite 子系统有关。我确定这是我正在做的事情。如果任何人都没有遇到过这种情况,那么我会发布代码,也许我们可以看到导致这种情况的原因。
  • 您是否尝试过开启核心数据 SQL 调试以查看实际执行的 SQL 是什么?
  • 不使用 WAL 模式会怎样?
  • SQL 调试(第 5 级)显示没有发生奇怪的 sql 查询。我将测试限制为 1000 条记录。 awl 文件增长到 877mb。 Xcode 中的控制台输出 86,231 行文本(总大小为 10.3mb)。

标签: ios iphone sqlite core-data import


【解决方案1】:

似乎我的评论尝试使用旧的回滚(DELETE)日志模式而不是 WAL 日志模式解决了这个问题。请注意,使用 WAL 日志模式时似乎存在一系列问题,包括:

  • 这个问题
  • 使用 migratePersistentStore API 时的数据库迁移问题
  • 轻量级迁移的问题

也许我们应该启动一个 Core Data WAL 问题页面并获得一个完整的列表并要求 Apple 修复错误。

请注意,OS X 10.9 和 iOS 7 下的默认模式现在使用 WAL 模式。要更改此选项,请添加以下选项

@{ NSSQLitePragmaOptions : @{ @"journal_mode" : @"DELETE" } }

【讨论】:

    【解决方案2】:

    事务的所有更改页面都附加到-wal 文件中。 如果您要导入多条记录,您应该 if possible 对整个导入使用单个事务。

    SQLite 无法执行完整的WAL checkpoint,而其他一些连接正在读取数据库(这可能只是您忘记关闭的某些语句)。

    【讨论】:

    • 如何“忘记关闭”核心数据事务?
    • 我这样做。我实际上已经禁用了上下文的撤消管理器,因为我不需要它(我认为它在 iOS 上默认为 nil,但我明确将其设置为 nil)。我只在整个循环完成并且所有托管对象都在 ram 中后才调用 save(顺便说一句,ram 上升到 100 MB)。核心数据对象的循环和创建只需要 5 秒左右。在写入 awl 文件时,保存需要将近 3 分钟。 (将此添加到主要问题中)
    • 好问题 Mundi。我确实明白,在 sqlite 世界中,如果您在数据库上打开了“Readers”(比如在其他线程中我正在读取 db),那么写入 db 文件的线程中的写入只会附加到 WAL 文件.这当然是有道理的——WAL 文件增长到超过 7GB 是没有意义的。我正在查看 sql 调试输出。随时通知您。
    • 来自 SQLite 网站:“但是,如果最后一个连接没有完全关闭,WAL 文件将保留在文件系统中,并在下次打开数据库时自动清理。”因此,即使在 sqlite 设置中“忘记关闭文件”,这也是无稽之谈。
    • @Mundi 可能的场景:单个应用程序启动事务但没有关闭它:所有更改都发布到 WAL,但是因为事务没有关闭,即既没有提交也没有回滚,WAL 文件只是不断增长和增长。
    猜你喜欢
    • 2018-05-16
    • 2018-08-07
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2021-08-11
    • 2013-09-11
    相关资源
    最近更新 更多