本人翻译, 原文见:
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, 我想我下一步得优化插入操作了.
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时候才写入文件系统. 因此我改动如下:
String sql = "INSERT INTO table (number, nick) VALUES (?, ?)"; db.beginTransaction(); 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(); } db.setTransactionSuccessful(); db.endTransaction();
结合transactions和 compiled statements后, 性能有了巨大的提升: 从71秒到不可置信的5秒! 在Galaxy上的结果更是牛逼: 从478秒到1.5秒!
结论:
- 除非你只执行单次的insert, 或者你需要数据立即写入文件系统, 不然的话就用transactions
- 保证你的程序在真机上测试过, 最好是多台机器上测.
- 我上面的性能提升只在Samsung Galaxy S上测过, 不同的机器可能还是会有性能问题.
相关推荐
下载来的资源,自己改了一下,共享出来,供小白使用,本想免费的,无奈最少是2分,再次吐槽一下csdn的下载规则变更,越来越商业化了。
Node.js结合sqlite3模块实现Sqlite数据库建表并实现大数据量的快速插入
网上收集的sqlite避免重复插入数据。
今天在向Sqlite数据库里插入数据的时候,报了这样一个错: 代码如下: “too many terms in compound SELECT” 去Stackoverflow上查了一下,发现有人回答这个问题:链接 原来一次性向数据库里插入数据的条数不能太...
android中SQLite数据库中用insert同时插入多条记录的方法和效率比较
NULL 博文链接:https://21jhf.iteye.com/blog/1915273
需要在sqlite数据库中插入大量测试数据,打算用事务进行循环插入操作,不过sqlite不支持declare变量定义,所以无法通过定义循环变量值来实现。需要通过一个批处理文件来循环调用插入sqlite语句,方式如下 建立一个...
主要介绍了C#/.Net 中快速批量给SQLite数据库插入测试数据,本文直接给出实例代码,需要的朋友可以参考下
Android中在sqlite插入数据的时候默认一条语句是一个事务,因此如果存在上万条数据插入的话,那需要执行上万次插入操作,操作速度可想而知。因此在Android中插入数据时,使用批量插入的方式可以大大提高插入速度。 ...
Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知。因此在Android中插入数据时,使用批量插入的方式可以大大提高插入速度...
sqlite3写入性能优化,使用事务结合执行准备的方法,极大地提升写入性能, 使用内存数据库(:memory:)模式高速写入,最后转存磁盘,也可提升部分性能
④实现了通用的sql语句执行帮助类(包含单条数据的插入、批量插入、事务处理、查询(指定内容查询、分页查询)、更新、删除等操作); ⑤可以直接获取Sqlite数据库中的所有表名称及其表包含的所有列名称; ⑥包含了...
在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。 首先说一下,IProvider里有一个用于实现...
做android和ios开发的一般都用Sqlite数据库,有的时候数据需要批量导入,那么如何导入呢? 在这里,介绍2种方法供大家参考。 一、用sqlite命令 以windows系统为例,linux下命令是一样的。 1.安装...
提高SQL的插入,更新,删除和合并性能,并克服SqlBulkCopy的限制稽核区分大小写实体数据源/ Lambda映射产值和更多...可扩展SQL Server-基准运作方式1,000行10,000行100,000行1,000,000行插6毫秒25毫秒200毫秒2,000...
支持10W行数据批量导入数据库。 支持防重复导入。
在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySQL也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解决方法。 首先说一下,IProvider里有一个用于实现...
增加目录,方便查询 SQLite学习手册(开篇) 一、简介 二、SQLite的主要优点 三、和RDBMS相比SQLite的一些劣势 四、个性化特征 SQLite学习手册(C/C++接口简介) ...三、高效的批量数据插入 四、数据查询