iOS SQLite慢性能

时间:2012-01-04 12:52:19

标签: objective-c ios multithreading performance sqlite

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

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

有没有办法在没有这些错误代码的多线程中执行此操作,还是应该放弃SQLite?

6 个答案:

答案 0 :(得分:3)

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

我对this recent question的回答应该指出我想的正确方向。

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

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

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

如上所述初始化队列:

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

[backgroundQueue setMaxConcurrentOperationCount:1];

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

将SQLite置于WAL模式。然后读取不会被阻止。不是这样写 - 你需要序列化它们。有多种方法可以实现它。其中一个是由SQLite提供的 - WAL钩子可以用来表示下一次写入可以启动。

WAL模式通常应该可以提高应用的性能。大多数事情都会快一些。读取不会被阻止。只有大型交易(几MB)才会放缓。一般没什么戏剧性的。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

OFF:

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

答案 5 :(得分:0)

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