SQLite插入非常慢?

我最近读了SQLite,并认为我会试一试。 当我插入一个logging时,它performance良好。 但是,当我插入一百个,需要五秒钟,而随着logging数量增加,时间也增加。 什么可能是错的? 我正在使用SQLite包装(system.data.SQlite)

 dbcon = new SQLiteConnection(connectionString); dbcon.Open(); //---INSIDE LOOP SQLiteCommand sqlComm = new SQLiteCommand(sqlQuery, dbcon); nRowUpdatedCount = sqlComm.ExecuteNonQuery(); //---END LOOP dbcon.close(); 

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(); 

尝试将所有插入(也称为批量插入)包装到单个事务中 :

 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将每个插入包装在一个事务中 ,这会降低进程的速度:

INSERT很慢 – 我每秒只能做几十个INSERT

实际上,SQLite在一台普通的桌面计算机上每秒钟很容易做到5万或更多的INSERT语句。 但是每秒只能做几十个交易。

事务速度受磁盘驱动器速度的限制,因为(默认情况下)SQLite实际上一直等到数据真正安全存储在磁盘表面上,然后事务完成。 那样的话,如果你突然失去电源,或者你的操作系统崩溃,你的数据仍然是安全的。 有关详细信息,请阅读SQLite中的primefaces提交。

默认情况下,每个INSERT语句都是它自己的事务。 但是,如果使用BEGIN … COMMIT包围多个INSERT语句,则所有插入操作都会分组到一个事务中。 提交事务所需的时间将在所有随附的插入语句之间进行摊销,因此每个插入语句的时间大大减less。

我到处读到,创build事务是减慢SQLite写入速度的解决scheme,但是重写代码并将所有SQLite写入事务处理可能是漫长而痛苦的。

我发现一个更简单,安全和非常有效的方法:我启用(默认情况下禁用)SQLite 3.7.0优化: 写前台日志(WAL) 。 该文档说,它适用于所有Unix(即Linux和OSX)和Windows系统。

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

 PRAGMA journal_mode = WAL PRAGMA synchronous = NORMAL 

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

请参阅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(); }