SQLite插入很慢?

时间:2010-10-03 23:59:42

标签: c# sqlite system.data.sqlite

我最近读过有关SQLite的内容,并认为我会尝试一下。当我插入一条记录时,它表现良好。但是当我插入一百个它需要五秒钟时,随着记录计数的增加,时间也会增加。可能有什么不对?我正在使用SQLite Wrapper (system.data.SQlite)

dbcon = new SQLiteConnection(connectionString);
dbcon.Open();

//---INSIDE LOOP

 SQLiteCommand sqlComm = new SQLiteCommand(sqlQuery, dbcon);

 nRowUpdatedCount = sqlComm.ExecuteNonQuery(); 

//---END LOOP

dbcon.close();

4 个答案:

答案 0 :(得分:75)

在批量插入内部包装BEGIN \ END语句。 Sqlite针对事务进行了优化。

dbcon = new SQLiteConnection(connectionString);
dbcon.Open();

SQLiteCommand sqlComm;
sqlComm = new SQLiteCommand("begin", dbcon);
sqlComm.ExecuteNonQuery(); 
//---INSIDE LOOP

 sqlComm = new SQLiteCommand(sqlQuery, dbcon);

 nRowUpdatedCount = sqlComm.ExecuteNonQuery(); 

//---END LOOP
sqlComm = new SQLiteCommand("end", dbcon);
sqlComm.ExecuteNonQuery(); 
dbcon.close();

答案 1 :(得分:31)

尝试将所有插页(也称为批量插入)包装到单个transaction

string insertString = "INSERT INTO [TableName] ([ColumnName]) Values (@value)";

SQLiteCommand command = new SQLiteCommand();
command.Parameters.AddWithValue("@value", value);
command.CommandText = insertString;
command.Connection = dbConnection;
SQLiteTransaction transaction = dbConnection.BeginTransaction();
try
{
    //---INSIDE LOOP
    SQLiteCommand sqlComm = new SQLiteCommand(sqlQuery, dbcon);
    nRowUpdatedCount = sqlComm.ExecuteNonQuery(); 
    //---END LOOP

    transaction.Commit();
    return true;
}
catch (SQLiteException ex)
{
    transaction.Rollback();
}

默认情况下,SQLite wraps every inserts in a transaction会降低流程速度:

  

INSERT非常慢 - 我每秒只能执行几十次INSERT

     

实际上,SQLite很容易在普通台式计算机上每秒执行50,000或更多INSERT语句。但它每秒只会进行几十次交易。

     

事务速度受磁盘驱动器速度的限制,因为(默认情况下)SQLite实际上等待,直到事务完成之前数据确实安全地存储在磁盘表面上。这样,如果您突然断电或者操作系统崩溃,您的数据仍然是安全的。有关详细信息,请阅读SQLite中的原子提交..

     

默认情况下,每个INSERT语句都是自己的事务。但是如果用BEGIN ... COMMIT包围多个INSERT语句,则所有插入都被分组到一个事务中。提交事务所需的时间在所有随附的insert语句中分摊,因此每个insert语句的时间大大减少。

答案 2 :(得分:29)

我到处都读到创建事务是减慢SQLite写入速度的解决方案,但重写代码并将所有SQLite写入事务包装在事务中可能会很长很痛苦。

我发现了一种更简单,安全且非常有效的方法:我启用了一个(默认情况下禁用)SQLite 3.7.0优化:Write-Ahead-Log (WAL)。 文档说它适用于所有unix(即Linux和OSX)和Windows系统。

怎么样?只需在初始化SQLite连接后运行以下命令:

PRAGMA journal_mode = WAL
PRAGMA synchronous = NORMAL

我的代码现在运行速度提高约600%:我的测试套件现在运行时间为38秒而不是4分钟:)

答案 3 :(得分:8)

请参阅ADO.NET帮助文件SQLite.NET.chm中的“优化SQL查询”。该页面的代码:

using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
{
  using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
  {
    SQLiteParameter myparam = new SQLiteParameter();
    int n;

    mycommand.CommandText = "INSERT INTO [MyTable] ([MyId]) VALUES(?)";
    mycommand.Parameters.Add(myparam);

    for (n = 0; n < 100000; n ++)
    {
      myparam.Value = n + 1;
      mycommand.ExecuteNonQuery();
    }
  }
  mytransaction.Commit();
}