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

时间:2010-12-04 23:13:48

标签: 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)
    {
        // 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;
    }

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

2 个答案:

答案 0 :(得分:27)

你肯定需要一笔交易。如果不这样做,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();
}

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

答案 1 :(得分: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 = 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;
        }
    }
}