SQLite .NET 性能,如何加快速度?

问题描述 投票:0回答:2

在我的系统上,大约 86000 个 SQLite 插入花费了 20 分钟,意味着每秒大约 70 次插入。我要做数百万,我怎样才能加快速度?对每一行的 SQLiteConnection 对象调用 Open() 和 Close() 会降低性能吗?交易有帮助吗?

单行典型插入方法:

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;
}

如您所见,插入非常简单。

c# .net performance sqlite insert
2个回答
36
投票

您肯定需要一笔交易。如果不这样做,SQLite 将为每个插入命令启动自己的事务,因此您实际上按原样执行了 86000 个事务。

看起来您每次都在打开和关闭连接,并且每次都重置 CommandText。这是不必要的,而且无疑会减慢你的速度,如果你满足以下条件,它会变得更快:

  • 打开连接一次
  • 构建命令一次,向其添加参数一次。
  • 开始交易
  • 循环,仅在调用 ExecuteNonQuery 之前更改参数值
  • 提交交易。
  • 关闭连接。

我认为这样你可以将 20 分钟减少到几秒钟。

编辑:这就是我的意思:

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

它只使用一个连接、一个事务和一个命令,因此您每次更改的只是参数值。


3
投票

使用交易。这应该会让事情变得更快。我还向您推荐以下模式:

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 = 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;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.