使用SQLite数据库在iPhone中的内存管理

3
我的应用程序使用SQLite数据库来存储用户输入。输入记录的数量将达到约100条,并且在应用程序中进行了许多SQL操作。
当我使用对象分配运行应用程序时,它显示sqlite库libsqlite3.0.dylib占用了大量内存。libsqlite框架会导致内存泄漏吗?与数据库通信的最佳方法是什么?有很多sql调用会增加我的应用程序的内存使用率。
请问有人能告诉我在应用程序中有效使用sqlite的最佳方法是什么。(我正在使用SQLiteBooks示例作为参考)
谢谢。
6个回答

8

Sqlite使用缓存来处理请求。定期关闭并重新打开数据库以释放缓存内存。

除非您的内存要求很高,否则不必关心。

您可以在UIApplicationDelegate方法applicationDidReceiveMemoryWarningUIViewController委托方法didReceiveMemoryWarning中捕获关键条件。

如果调用了其中一个方法,请关闭并重新打开数据库。


谢谢Stephan。但如果我这样做而有些查询没有完全执行,操作会回滚还是会完成然后关闭数据库? - lostInTransit
如果您使用BEGIN ... COMMIT事务,当数据库关闭时,事务将会回滚。 - Stephan Burlot
嗨,Stephen。关闭数据库并重新打开时出现了以下异常:http://stackoverflow.com/questions/449933/sqlite-terminating-app-due-to-uncaught-exception-nsinternalinconsistencyexc - lostInTransit

5

我从未见过由sqlite引起的内存泄漏。它确实使用了相当大的内存,但想想你需要写多少代码和缓存多少数据来完成同样的事情...

最好的建议是使用高效的SQL,并尽快重置语句句柄。虽然我没有发现有必要这样做,但完成准备好的语句也可能有所帮助。

人们经常建议定期关闭和重新打开数据库。虽然这样做不会有任何损失,但我自己没有看到任何实际的好处。

最后,在sqlite网站上,你会看到关于functions to manage memory的讨论。这些听起来很诱人,直到你意识到它们是可选的,并且在iPhone上的默认构建中未启用。


谢谢Stephen。我没有缓存任何来自数据库的数据,所有数据只在需要时才读取。重置也会在语句函数结束后立即完成。我还会完成语句。还有其他建议吗?再次感谢。 - lostInTransit

4

PRAGMA在iPhone上没有帮助,因为苹果提供了二进制库。 - brianegge
3
PRAGMAs在运行时执行,而不是编译时。 - Doug Currie

3

当连续进行许多INSERTs(> 1000)时,我发现SQLite的内存使用量会急剧上升。写入性能也很慢。将执行INSERTs的循环包装在事务中,可以减少这些问题的影响。我在回答这个问题时发布了一些示例代码。


1
这是因为SQLite使用其页面缓存的方式。如果您将INSERT / UPDATE语句放入事务中,它仅在内存中进行修改,然后在提交时批量写入它们。如果您没有显式事务,则SQLite会在每个INSERT,UPDATE或DELETE周围放置隐式事务。此外,即使您只修改了该页面中的单个数据位,SQLite也始终更新整个4k DB页面。 - orj

2

您确实希望限制iPhone应用程序中SQLite的缓存大小。启动应用程序并初始化数据库时,请运行以下命令:

const char *pragmaSql = "PRAGMA cache_size = 50";
if (sqlite3_exec(database, pragmaSql, NULL, NULL, NULL) != SQLITE_OK) {
    NSAssert1(0, @"Error: failed to execute pragma statement with message '%s'.", sqlite3_errmsg(database));
}

这将防止 SQLite 缓存您的查询并慢慢消耗所有内存。


我应该在执行每个SQL事务时这样做吗? - Sunil Targe

1

我曾经看到过内存使用率因为索引不良而在相对较大的数据库中激增。如果你为数据库添加一些深思熟虑的索引,这是一个快速简便的方式来让内存使用率回归现实世界。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接