今天接到一个Ticket,说SQLite数据库的访问太慢。用VisualVM一查,两个访问函数需要分别消耗~200秒和~300秒。真不太能接受,想想如何解决吧。
问题分析
SQLite数据量大约有40K,其实数据量并不大,主要问题一定还出在SQLite的表结构上。在这个应用中,我们需要根据现有数据和用户的输入,在线计算很多新的列,还要支持排序,过滤等操作。为了避免磁盘IO,定义了很多的View,没有生成新的Table。虽然没有在SQLite的网上查到具体说明,但问题一定就出在这些View的定义上。恰好是因为没有生成Table,View的每次生成计算反而需要更多时间。
问题解决
那如何能生成Table,并避免大量读写操作呢?想到SQLite支持In-memory DB, 所以应该可以把这一切的操作放到内存里。这里的Java示例代码说明如何使用In-memory DB.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// Create a memory database Connection conn = DriverManager.getConnection("jdbc:sqlite:"); // Do some updates stmt.executeUpdate("create table sample(id, name)"); stmt.executeUpdate("insert into sample values(1, \"leo\")"); stmt.executeUpdate("insert into sample values(2, \"yui\")"); // Dump the database contents to a file stmt.executeUpdate("backup to backup.db"); Restore the database from a backup file: // Create a memory database Connection conn = DriverManager.getConnection("jdbc:sqlite:"); // Restore the database from a backup file Statement stat = conn.createStatement(); stat.executeUpdate("restore from backup.db"); |
具体思路:
- 新建In-memory database
- 把目标数据库restore到database中(前提是我们的数据量不大,并且生成后不会有变化)
- 不用View,全部使用Table,用户输入变化时,就重新写Table。
结果
当我看到改进之后的函数访问时间在VisualVM上变成0.0ms时,我知道这个Ticket可以Resolve了。^_^