C# SQLite.NET性能如何提高?
在我的系统上,大约86000次SQLite插入耗时20分钟,即每秒约70次插入。我要做几百万,我怎样才能加快速度?对每行SQLiteConnection对象调用Open()和Close()会降低性能吗?交易有帮助吗 单线的典型插入方法:C# SQLite.NET性能如何提高?,c#,.net,performance,sqlite,insert,C#,.net,Performance,Sqlite,Insert,在我的系统上,大约86000次SQLite插入耗时20分钟,即每秒约70次插入。我要做几百万,我怎样才能加快速度?对每行SQLiteConnection对象调用Open()和Close()会降低性能吗?交易有帮助吗 单线的典型插入方法: public int InsertResultItem(string runTag, int topicId, string documentNumber, int rank, double score) { //
public int InsertResultItem(string runTag, int topicId,
string documentNumber, int rank, double score)
{
// Apre la connessione e imposta il comando
connection.Open();
command.CommandText = "INSERT OR IGNORE INTO Result "
+ "(RunTag, TopicId, DocumentNumber, Rank, Score) " +
"VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)";
// Imposta i parametri
command.Parameters.AddWithValue("@RunTag", runTag);
command.Parameters.AddWithValue("@TopicId", topicId);
command.Parameters.AddWithValue("@DocumentNumber", documentNumber);
command.Parameters.AddWithValue("@Rank", rank);
command.Parameters.AddWithValue("@Score", score);
// Ottieni il risultato e chiudi la connessione
int retval = command.ExecuteNonQuery();
connection.Close();
return retval;
}
如您所见,插入非常简单。使用事务。这会让事情变得更快。此外,我还向您推荐以下模式:
public int InsertResultItem(string runTag, int topicId,
string documentNumber, int rank, double score)
{
// Apre la connessione e imposta il comando
using (var connection = new SQLiteConnection(SomeConnectionString))
using (var command = new connection.CreateCommand())
{
connection.Open();
using (var tx = connection.BeginTransaction())
{
command.CommandText = "INSERT OR IGNORE INTO Result "
+ "(RunTag, TopicId, DocumentNumber, Rank, Score) " +
"VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)";
// Imposta i parametri
command.Parameters.AddWithValue("@RunTag", runTag);
command.Parameters.AddWithValue("@TopicId", topicId);
command.Parameters.AddWithValue("@DocumentNumber", documentNumber);
command.Parameters.AddWithValue("@Rank", rank);
command.Parameters.AddWithValue("@Score", score);
// Ottieni il risultato e chiudi la connessione
var retval = command.ExecuteNonQuery();
tx.Commit();
return retval;
}
}
}
你肯定需要一笔交易。如果您不这样做,SQLite会为每个insert命令启动自己的事务,这样您就可以按原样有效地执行86000个事务 看起来您每次都在打开和关闭连接,同时每次都重置CommandText。这是不必要的,毫无疑问会让你慢下来,如果你:
- 打开连接一次
- 生成一次命令,向其中添加一次参数
- 启动事务
- 循环,仅在调用ExecuteOnQuery之前更改参数值
- 提交事务
- 关闭连接
public void InsertItems()
{
SQLiteConnection connection = new SQLiteConnection(SomeConnectionString);
SQLiteCommand command = connection.CreateCommand();
SQLiteTransaction transaction = connection.BeginTransaction();
command.CommandText = "INSERT OR IGNORE INTO Result "
+ "(RunTag, TopicId, DocumentNumber, Rank, Score) " +
"VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)";
command.Parameters.AddWithValue("@RunTag", "");
command.Parameters.AddWithValue("@TopicId", "");
command.Parameters.AddWithValue("@DocumentNumber", "");
command.Parameters.AddWithValue("@Rank", "");
command.Parameters.AddWithValue("@Score", "");
foreach ( /* item to loop through and add to db */ )
{
InsertResultItem(runTag, topicId, documentNumber, rank, score, command);
}
transaction.Commit();
command.Dispose();
connection.Dispose();
}
public int InsertResultItem(string runTag, int topicId, string documentNumber, int rank, double score, SQLiteCommand command)
{
command.Parameters["@RunTag"].Value = runTag;
command.Parameters["@TopicId"].Value = topicId;
command.Parameters["@DocumentNumber"].Value = documentNumber;
command.Parameters["@Rank"].Value = rank;
command.Parameters["@Score"].Value = score;
return command.ExecuteNonQuery();
}
它只使用一个连接、一个事务和一个命令,所以每次更改的只是参数值 由于InsertResultItem看起来像是在循环中调用的,这仍然是打开一个新连接,启动一个新事务,并为每个插入生成一个新命令。速度与OP代码中的速度相同。@miket2e,这不是打开新连接,ADO.NET使用连接池。另外,启动一个新事务正是加快速度的原因。不过,它为每个插入创建一个事务。SQLite是隐式的()如果您没有显式地声明它,这就是我所说的相同的意思。它需要是一个围绕所有插入的事务,才能发挥作用。我不确定他是否在使用ADO.NET,如果他在应用程序中使用嵌入的SQLite(没有ADO.NET),那么只连接一次也会更快。是的,每次提取新行时,循环都会调用InsertResultItem。所以使用事务是没有用的?不,它不是没有用的,事务会使它更快。您只需要对代码进行一点重构,以便只使用一个事务,而不是数千个事务。比方说,首先创建命令,然后将其作为参数传递给InsertResultItem-不要每次都重新创建它。我不能,因为循环在另一个类中。。。如何实现IDisposable并在Dispose()上提交事务?我认为如何实现它的细节实际上取决于您,只要您只使用一个连接/事务/命令,它将比您目前的速度快得多。从20分钟减少到1分钟。太棒了,感谢所有人!通过使用这个方法,我可以在时间上进一步减少1/4,使用更大的准备好的INSERT语句,一次插入10行,参数是原来的10倍。我认为它更快,因为它进行的本机互操作调用更少。我的性能指标:在不使用事务的情况下插入100行需要19832.0毫秒。使用事务插入10000行需要797.0毫秒。看起来交易是唯一的主导因素。