Android下SQLite数据库一条条地插入记录太慢了,1000条记录要30来秒时间,怎么改进?
解决方案 »
- 请问哪位大侠知道android所有app权限汇集的一个文件叫什么名?
- android的重定向问题
- 高通7627 UART设备加载问题
- asp转化为JSON数据类,然后在Android中调用
- 平板电脑USB驱动问题
- 单击按钮,在屏幕上画一条直线
- 开发微信商城,该怎么做?
- Android下usb host接口插入usb设备时,如何屏蔽usb权限的提示框? 如何自动获取usb设备的权限?
- Android,Webview的loadUrl的地址可以在服务器端修改吗,还是只可以写死?
- 更新jdk,eclipse发生错误,之前游泳的代码现在都打红叉
- 40分求画时序图的软件,推荐一个即可,恳请帮忙
- 求助,socket连接网络调试助手,能发不能收??
今天有个朋友测试 SQLite,然后得出的结论是:SQLite 效率太低,批量插入1000条记录,居然耗时 2 分钟!
下面是他发给我的测试代码。我晕~~~~~~
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
// 创建数据库文件
File.Delete("test1.db3");
SQLiteConnection.CreateFile("test1.db3");
DbProviderFactory factory = SQLiteFactory.Instance;
using (DbConnection conn = factory.CreateConnection())
{
// 连接数据库
conn.ConnectionString = "Data Source=test1.db3";
conn.Open();
// 创建数据表
string sql = "create table [test1] ([id] INTEGER PRIMARY KEY, [s] TEXT COLLATE NOCASE)";
DbCommand cmd = conn.CreateCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
// 添加参数
cmd.Parameters.Add(cmd.CreateParameter());
// 开始计时
Stopwatch watch = new Stopwatch();
watch.Start();
// 连续插入1000条记录
for (int i = 0; i < 1000; i++)
{
cmd.CommandText = "insert into [test1] ([s]) values (?)";
cmd.Parameters[0].Value = i.ToString();
cmd.ExecuteNonQuery();
}
// 停止计时
watch.Stop();
Console.WriteLine(watch.Elapsed);
}
哎~~~~ 一个常识性的错误,我加几行代码 (新增代码标记 "// <-------------------")。
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
// 创建数据库文件
File.Delete("test1.db3");
SQLiteConnection.CreateFile("test1.db3");
DbProviderFactory factory = SQLiteFactory.Instance;
using (DbConnection conn = factory.CreateConnection())
{
// 连接数据库
conn.ConnectionString = "Data Source=test1.db3";
conn.Open();
// 创建数据表
string sql = "create table [test1] ([id] INTEGER PRIMARY KEY, [s] TEXT COLLATE NOCASE)";
DbCommand cmd = conn.CreateCommand();
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
// 添加参数
cmd.Parameters.Add(cmd.CreateParameter());
// 开始计时
Stopwatch watch = new Stopwatch();
watch.Start();
DbTransaction trans = conn.BeginTransaction(); // <-------------------
try
{
// 连续插入1000条记录
for (int i = 0; i < 1000; i++)
{
cmd.CommandText = "insert into [test1] ([s]) values (?)";
cmd.Parameters[0].Value = i.ToString();
cmd.ExecuteNonQuery();
}
trans.Commit(); // <-------------------
}
catch
{
trans.Rollback(); // <-------------------
throw; // <-------------------
}
// 停止计时
watch.Stop();
Console.WriteLine(watch.Elapsed);
}
执行一下,耗时 0.2 秒。这差距是不是太大了点?
为什么只是简单启用了一个事务会有这么大的差距呢?很简单,SQLite 缺省为每个操作启动一个事务,那么原代码 1000 次插入起码开启了 1000 个事务,"事务开启 + SQL 执行 + 事务关闭" 自然耗费了大量的时间,这也是后面显示启动事务后为什么如此快的原因。其实这是数据库操作的基本常识,大家要紧记,不好的代码效率差的不是一点半点。
上面使用事务快了很多,不知道ANDROID下的SQLITE怎么使用事务。
最近在做android项目的时候遇到一个问题,应用程序初始化时需要批量的向sqlite中插入大量数,导致应用启动过慢。android使用的是sqlite数据库,sqlite是比较轻量级的数据库,在Google了之后发现,sqlite事务处理的问题,在sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。我的应用初始5000条记录也就是要5000次读写磁盘操作。解决方法:添加事务处理,把5000条插入作为一个事务dataBase.beginTransaction(); //手动设置开始事务//数据插入操作循环dataBase.setTransactionSuccessful(); //设置事务处理成功,不设置会自动回滚不提交dataBase.endTransaction(); //处理完成
SQLITE 3 插入或更新一条数据的时间,可能达到100多MS。对于多条数据的批次插入或更新,可以使用事务的方法解决。如果只是插入单条数据,而且数据安全没那么重要(不怕断电,或系统意外关闭,丢掉数据),可以在open db 后执行sqlite3_exec(pdb,“PRAGMA synchronous = OFF; ”,0,0,&szErr);试试加快速度.
SQLite的数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很好时的过程,会极大地影响数据库存取的速度。
例如:向数据库中插入100万条数据,在默认的情况下如果仅仅是执行
sqlite3_exec(db, “insert into name values ‘lxkxf', ‘24'; ”, 0, 0, &zErrMsg);
将会重复的打开关闭数据库文件100万次,所以速度当然会很慢。因此对于这种情况我们应该使用“事务”。
具体方法如下:在执行SQL语句之前和SQL语句执行完毕之后加上
rc = sqlite3_exec(db, "BEGIN;", 0, 0, &zErrMsg);
//执行SQL语句
rc = sqlite3_exec(db, "COMMIT;", 0, 0, &zErrMsg);
这样SQLite将把全部要执行的SQL语句先缓存在内存当中,然后等到COMMIT的时候一次性的写入数据库,这样数据库文件只被打开关闭了一次,效率自然大大的提高。有一组数据对比:
测试1: 1000 INSERTs
CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
SQLite 2.7.6:
13.061
SQLite 2.7.6 (nosync):
0.223测试2: 使用事务 25000 INSERTs
BEGIN;
CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two');
... 24997 lines omitted
INSERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine');
INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six');
COMMIT;
SQLite 2.7.6:
0.914
SQLite 2.7.6 (nosync):
0.757可见使用了事务之后却是极大的提高了数据库的效率。但是我们也要注意,使用事务也是有一定的开销的,所以对于数据量很小的操作可以不必使用,以免造成而外的消耗。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jacky_jin/archive/2010/03/23/5407945.aspx
.beginTransaction();
cmd.exec();
.Commit();
2009-02-04 17:19
sqlite3 *db;
sqlite3_open(theApp.getDB_fullPath(), &db);
sqlite3_exec(db,"BEGIN TRANSACTION",0,0,0);
sqlite3_exec(db,"update tabConfFeichengRen set value="+yingEr+" where type='yingEr'",0,0,0);
sqlite3_exec(db,"update tabConfFeichengRen set value="+erTong+" where type='erTong'",0,0,0);
sqlite3_exec(db,"update tabConfFeichengRen set value="+erTongJiaChuang+" where type='erTongJiaChuang'",0,0,0);
int rc=sqlite3_exec(db,"COMMIT",0,0,0);if(rc!=SQLITE_OK)
{
AfxMessageBox("出错!");
}
else
{
AfxMessageBox("OK!");
}
sqlite3_close(db);