SQLite 批量insert - 如何加速SQLite的插入操做

本人翻譯, 原文見:sql

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代碼   收藏代碼
  1. String sql = "INSERT INTO table (number, nick) VALUES (?, ?)";  
  2. SQLiteStatement stmt = db.compileStatement(sql);  
  3. for (int i = 0; i < values.size(); i++) {  
  4.     stmt.bindString(1, values.get(i).number);  
  5.     stmt.bindString(2, values.get(i).nick);  
  6.     stmt.execute();  
  7.     stmt.clearBindings();  
  8. }  

 

有了上面的改動後, 我在模擬器上測試, 時間從71秒減小到56秒, 可是在真機上測的時候, 時間反而多了幾秒, 我反覆測了幾回, 仍是差很少同樣的結果.測試

 

進一步研究, 我從SQLite的一個文檔頁面看到「PRAGMA synchronous = OFF」 將會告訴SQLite, 當它把數據傳入操做系統的時候, 不要當即同步. 這個設置讓插入時間從71秒減小的50秒, 在真機上的結果是361秒, 差很少快2分鐘.優化

 

感受到找到路子以後, 我認爲是文件系統減慢了插入操做, 我在網上找到了不少關於Galaxy S I/O 性能問題的參考 - 全部的都與RFS文件系統相關. 對於SQLite而言, 它每插入一次數據, 都會執行一下fsync, 以保證數據寫入了磁盤. 再看SQLite文檔, 我發現用transactions可以將數據保存在內存中, 只有在commit時候才寫入文件系統. 所以我改動以下:spa

 

Java代碼   收藏代碼
  1. String sql = "INSERT INTO table (number, nick) VALUES (?, ?)";  
  2. db.beginTransaction();  
  3.    
  4. SQLiteStatement stmt = db.compileStatement(sql);  
  5. for (int i = 0; i < values.size(); i++) {  
  6.     stmt.bindString(1, values.get(i).number);  
  7.     stmt.bindString(2, values.get(i).nick);  
  8.     stmt.execute();  
  9.     stmt.clearBindings();  
  10. }  
  11.    
  12. db.setTransactionSuccessful();  
  13. db.endTransaction();  

 

結合transactions和 compiled statements後, 性能有了巨大的提高: 從71秒到不可置信的5秒! 在Galaxy上的結果更是牛逼: 從478秒到1.5秒!操作系統

 

結論:翻譯

- 除非你只執行單次的insert, 或者你須要數據當即寫入文件系統, 否則的話就用transactionssqlite

- 保證你的程序在真機上測試過, 最好是多臺機器上測.

- 我上面的性能提高只在Samsung Galaxy S上測過, 不一樣的機器可能仍是會有性能問題.

相關文章
相關標籤/搜索