本人翻譯, 原文見:
http://tech.vg.no/2011/04/04/speeding-up-sqlite-insert-operations/
我正在開發一個Android程式, 它使用SQLite存儲大約6000行的資料, 這些資料會定期從網上更新. 在模拟器上, 從網絡擷取和解析CSV格式的資料所花的時間大概是20秒, 但是把資料插入的資料庫的時間是71秒.
因為資料更新的操作差不多一個星期才有一次, 是以我認為1分多鐘的操作時間是可以接受的. 但當我把程式在真機上跑的時候, 6000行的插入時間讓我吓了一跳 -- 478秒, 差不多8分鐘. 很奇怪, 一般來說, 真機要比模拟器快, 何況我用的是Sanmsung Galaxy S - 當時最快的Android裝置之一. 這是我第一次使用SQLite, 我想我下一步得優化插入操作了.
Sql代碼

- String sql = "INSERT INTO table (number, nick) VALUES (?, ?)";
- SQLiteStatement stmt = db.compileStatement(sql);
- for (int i = 0; i < values.size(); i++) {
- stmt.bindString(1, values.get(i).number);
- stmt.bindString(2, values.get(i).nick);
- stmt.execute();
- stmt.clearBindings();
- }
有了上面的改動後, 我在模拟器上測試, 時間從71秒減少到56秒, 但是在真機上測的時候, 時間反而多了幾秒, 我反複測了幾次, 還是差不多一樣的結果.
進一步研究, 我從SQLite的一個文檔頁面看到“PRAGMA synchronous = OFF” 将會告訴SQLite, 當它把資料傳入作業系統的時候, 不要立即同步. 這個設定讓插入時間從71秒減少的50秒, 在真機上的結果是361秒, 差不多快2分鐘.
感覺到找到路子之後, 我認為是檔案系統減慢了插入操作, 我在網上找到了很多關于Galaxy S I/O 性能問題的參考 - 所有的都與RFS檔案系統相關. 對于SQLite而言, 它每插入一次資料, 都會執行一下fsync, 以保證資料寫入了磁盤. 再看SQLite文檔, 我發現用transactions能夠将資料儲存在記憶體中, 隻有在commit時候才寫入檔案系統. 是以我改動如下:
Java代碼

- db.beginTransaction();
- db.setTransactionSuccessful();
- db.endTransaction();
結合transactions和 compiled statements後, 性能有了巨大的提升: 從71秒到不可置信的5秒! 在Galaxy上的結果更是牛逼: 從478秒到1.5秒!
結論:
- 除非你隻執行單次的insert, 或者你需要資料立即寫入檔案系統, 不然的話就用transactions
- 保證你的程式在真機上測試過, 最好是多台機器上測.
- 我上面的性能提升隻在Samsung Galaxy S上測過, 不同的機器可能還是會有性能問題.