Производительность SQLite .NET, как ускорить процесс? - PullRequest
15 голосов
/ 05 декабря 2010

В моей системе ~ 86000 вставок SQLite занимали до 20 минут, что означает ~ 70 вставок в секунду.Я должен сделать миллионы, как я могу ускорить это?Вызов Open () и Close () для объекта SQLiteConnection для каждой строки может снизить производительность?Могут ли помочь транзакции?

Типичный метод вставки для одной строки:

    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 ]

27 голосов
/ 05 декабря 2010

Вам определенно нужна транзакция. Если вы этого не сделаете, 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 голосов
/ 05 декабря 2010

Использование транзакций.Это должно сделать вещи быстрее.Также я бы порекомендовал вам следующий шаблон:

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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...