Android下SQLite数据库一条条地插入记录太慢了,1000条记录要30来秒时间,怎么改进?

解决方案 »

  1.   

    SQLite速度评测代码 http://www.cppblog.com/woaidongmao/archive/2009/06/19/88103.html
    今天有个朋友测试 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怎么使用事务。
      

  2.   

    SQLite 插入速度的确慢,插入一个记录要 100ms 左右http://bbs.gimoo.net/thread/71557-1.html
      

  3.   

    android sqlite批量插入数据速度解决方案http://www.cnblogs.com/tinggu/archive/2010/08/31/1813433.html
    最近在做android项目的时候遇到一个问题,应用程序初始化时需要批量的向sqlite中插入大量数,导致应用启动过慢。android使用的是sqlite数据库,sqlite是比较轻量级的数据库,在Google了之后发现,sqlite事务处理的问题,在sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。我的应用初始5000条记录也就是要5000次读写磁盘操作。解决方法:添加事务处理,把5000条插入作为一个事务dataBase.beginTransaction();        //手动设置开始事务//数据插入操作循环dataBase.setTransactionSuccessful();        //设置事务处理成功,不设置会自动回滚不提交dataBase.endTransaction();        //处理完成 
      

  4.   

    sqlite3 单条记录插入,更新速度慢的问题 http://www.cppblog.com/mcs51a/archive/2010/03/18/109984.aspx
     SQLITE 3 插入或更新一条数据的时间,可能达到100多MS。对于多条数据的批次插入或更新,可以使用事务的方法解决。如果只是插入单条数据,而且数据安全没那么重要(不怕断电,或系统意外关闭,丢掉数据),可以在open db 后执行sqlite3_exec(pdb,“PRAGMA synchronous = OFF; ”,0,0,&szErr);试试加快速度.
      

  5.   

    SQLite 插入速度的确慢,插入一个记录要 100ms 左右http://topic.csdn.net/u/20080706/01/034ac8b4-70c5-460a-b771-5d6bbee35078.html
      

  6.   

    SQLite批量插入优化方法http://blog.csdn.net/jacky_jin/archive/2010/03/23/5407945.aspx
    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
      

  7.   

    使用SQLite提供的事务方式操作数据库。使用事务机制时,1000条记录只有1个I/O操作,不使用事务机制时是1000个I/O操作,一个IO操作算25毫秒的话,那么1000个I/O操作就是25秒了。所以1000条记录使用事务操作比不使用事务操作省了25秒
      

  8.   

    Actually, SQLite will easily do 50,000 or more INSERT statements per second on an average desktop computer. But it will only do a few dozen transactions per second. Transaction speed is limited by the rotational speed of your disk drive. A transaction normally requires two complete rotations of the disk platter, which on a 7200RPM disk drive limits you to about 60 transactions per second. By default, each INSERT statement is its own transaction. But if you surround multiple INSERT statements with BEGIN...COMMIT then all the inserts are grouped into a single transaction. The time needed to commit the transaction is amortized over all the enclosed insert statements and so the time per insert statement is greatly reduced. 
      

  9.   

    确实,android中做一些sql的循环操作,需要加上事务的处理。不然效率太差了
      

  10.   

    想提高效率,自定义格式,别用sqlite啊,文件系统级别还是很快的,如果感觉慢,可以上mmap用内存文件,效果打打滴
      

  11.   

    用事务来处理
    .beginTransaction();  
    cmd.exec();
    .Commit();
      

  12.   

    我也刚刚解决了这个问题,很不错,!1sqlite,sqlite3_exec执行事务批量更新记录
    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);
      

  13.   

    想问一下各位,你们启用事务的话,内存和CPU能吃的消么?我启用后咋更慢了,只看到系统一直在放内存
      

  14.   

    android系统自带的launcher2源代码有这方面的代码可以参考!!!beginTransactionendTransactionsendNotify