【问题标题】:iOS SQLite Slow PerformanceiOS SQLite 性能缓慢
【发布时间】:2012-01-04 12:52:19
【问题描述】:

我在我的 iOS 应用程序中使用 SQLite,当用户与 UI 交互时,我有很多保存/加载工作要做。这是一个问题,因为它使 UI 非常不稳定和缓慢。

我尝试在另一个线程中执行这些操作,但我认为这在 SQLite 中是不可能的。如果我这样做,我会经常收到错误代码 SQLITE_BUSY 和 SQLITE_LOCKED。

有没有办法在多线程中做到这一点而没有这些错误代码,还是我应该放弃 SQLite?

【问题讨论】:

  • 您是否尝试过调整您使用的查询并查看查询计划以查看是否需要任何索引?
  • 进行多次写入时是否使用事务?你应该 - 它会产生巨大的影响。
  • Frederick Cheung:我正在使用多次写入和检索。我会看看索引是否会有所帮助,但是要插入很多记录,所以我认为索引不会有帮助。 Hot Licks:我在使用多次写入时不进行事务处理。我应该使用相同的锁对数据库中的每次写入执行此操作吗?
  • 您应该将一组写入与事务括起来。否则每次写入都是 start-transaction/write/end-transaction,并且它是 end-transaction 需要的所有时间。 (这在 SQLite 文档中有明确说明。)

标签: objective-c ios multithreading performance sqlite


【解决方案1】:

完全有可能,您只需在后台线程中序列化对 SQLite 的访问即可。

我对@9​​87654321@ 的回答应该会为您指明正确的方向。

正如在其他地方提到的,SQLite 适合并发读取,但在数据库级别锁定以进行写入。这意味着如果你在不同的线程中读写,你会得到 SQLITE_BUSY 和 SQLITE_LOCKED 错误。

避免这种情况的最基本方法是在调度队列或并发为 1 的 NSOperationQueue 中序列化 所有 DB 访问(读取和写入)。因为这种访问不是发生在主线程上,您的 UI 不会受到影响。

这显然会停止读取和写入重叠,但它也会停止同时读取。目前尚不清楚这是否会影响您的性能。

如上所述初始化队列:

NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];

[backgroundQueue setMaxConcurrentOperationCount:1];

然后您可以根据需要将操作添加到队列中。

【讨论】:

  • 我试过这样做,但仍然遇到错误。我现在正在使用调度队列。
  • 你现在一切正常吗?调度队列也应该没问题。
  • 不,使用调度队列后,我不断收到 SQLITE_BUSY 和 SQLITE_LOCKED 错误代码。还有一些奇怪的行为,比如视图被提前弹出等等。
  • 然后我们需要查看您的调度队列周围的代码。根据 Apple 的文档,“提交到串行队列的块按 FIFO 顺序一次执行一个”。
  • 问题是即使在队列完成之后,我也会得到 SQLITE_BUSY 和 SQLITE_LOCKED。
【解决方案2】:

将所有内容都放在一个专用的 SQLite 线程或一次一个操作的操作队列中是很好的解决方案,尤其是在解决您紧张的 UI 时。另一种技术(可能对抖动没有帮助)是发现这些错误代码,然后简单地循环,重试更新,直到获得成功的返回代码。

【讨论】:

    【解决方案3】:

    将 SQLite 置于 WAL 模式。然后读取不会被阻止。不是这样写的——你需要序列化它们。有多种方法可以实现它。其中一个由 SQLite 提供 - WAL 挂钩可用于发出下一次写入可以开始的信号。

    WAL 模式通常可以提高应用的性能。大多数事情会快一点。读取根本不会被阻止。只有大事务(几 MB)会变慢。一般没有什么戏剧性的。

    【讨论】:

      【解决方案4】:

      不要放弃 SQLite。您绝对可以在不同于 UI 线程的线程中执行此操作,以避免运行缓慢。只需确保一次只有 一个 线程访问数据库。 SQLite 在处理并发访问时不是很好。

      【讨论】:

      • 并发 reads 没问题,但是 updates 会锁定其他所有内容(由于比 DB 级锁定更细粒度的任何事情都比较复杂) .
      • 我的问题是我无法控制用户何时访问/写入数据。例如,在一个视图上,它将读取和保存数据,但随后他们可以单击详细信息并推送一个也想要读取/写入数据的新视图。不知道如何确保一个线程同时访问数据库。
      【解决方案5】:

      我建议使用位于 sqlite 之上的 Core Data。我在多线程环境中使用它。这是Concurrency with Core Data 的指南。

      【讨论】:

        【解决方案6】:

        关:

        你结帐了吗:FMDB 它是一个 sqlite Wrapper 并且是线程安全的。我在我所有的 sqlite 项目中都使用了它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-14
          • 2015-01-27
          • 2021-06-04
          • 2016-11-09
          • 2021-06-21
          • 2012-05-11
          相关资源
          最近更新 更多