我最近读过有关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();
答案 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();
}