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上测过, 不一样的机器可能仍是会有性能问题.

相关文章
相关标签/搜索