Повышение производительности массовых вставок SQLite с помощью Dapper ORM - PullRequest
10 голосов
/ 25 января 2012

Я работаю над настольным приложением, которое использует SQLite для массовой вставки десятков тысяч строк в базу данных SQLite. Я хотел бы помочь в оптимизации производительности массовой вставки. В настоящее время вставка данных в базу данных занимает 60 мегабайт.

  • какие параметры строки подключения можно использовать для улучшения спектакль? Должен ли я изменить размер буфера? Это возможно через параметр строки подключения? Есть ли другая строка подключения параметры для улучшения производительности? Моя текущая строка подключения:

    Источник данных = Batch.db; Версия = 3; Пул = Истина; Макс. Пул Размер = 10; Синхронный = выкл; FailIfMissing = Истина; Режим журнала = Выкл;

  • Я использую Dapper ORM. (построено ребятами из StackOverflow) Есть ли более быстрый способ массовой вставки в Sqlite, в .net?

  • System.Data.Sqlite используется для вставки в SQLite. Как насчет получения специальной скомпилированной версии sqlite, которая улучшает спектакль? Одна версия SQLite лучше другой? В настоящее время используя System.Data.SQLite из http://sqlite.phxsoftware.com

  • В настоящее время я обертываю вставки внутри транзакции, чтобы сделать их быстрее (это стало хорошим улучшением).

  • Я вставляю по одной таблице за раз в 17 таблиц. Могу ли я распараллелить это на разных потоках и сделать это быстрее?

Текущее исполнение. Это типично? Могу ли я сделать лучше?

  • 55 000 строк в таблицу с 19 столбцами: 2,25 с для вставки (24 тыс. Вставок / с)
  • 10000 строк в таблице с 63 столбцами: 2,74 с для вставки (3,7 к / с)

Мне нравится SQLite, но я бы хотел сделать его немного быстрее. В настоящее время сохранение моих объектов в XML-файл с использованием сериализации XML происходит быстрее, чем сохранение в базе данных SQLite, поэтому мой начальник спрашивает: зачем переходить на SQLite? Или я должен использовать MongoDB или какую-либо другую объектную базу данных?

Ответы [ 2 ]

14 голосов
/ 03 февраля 2012

Итак, я наконец-то нашел способ высокопроизводительных массовых вставок в SQLite с использованием .NET.Этот прием улучшил производительность вставки в 4,1 раза!Мое общее время сохранения увеличилось с 27 до 6,6 секунд.Вот Это Да!

В этой статье описывается самый быстрый способ массовых вставок в SQLite .Ключ повторно использует те же самые объекты параметров, но для каждой записи, чтобы вставить, назначая различное значение.Время, которое требует .NET на создание всех этих объектов DbParameter, действительно складывается.Например, с 100 000 строк и 30 столбцов = 3 миллиона объектов параметров, которые должны быть созданы.Вместо этого создание и повторное использование только 30 объектов параметров выполняется намного быстрее.

Новая производительность:

  • 55 000 строк (19 столбцов) за .53 секунды = 100 тыс. Вставок / секунду

        internal const string PeakResultsInsert = @"INSERT INTO PeakResult values(@Id,@PeakID,@QuanPeakID,@ISTDRetentionTimeDiff)";
    
                var command = cnn.CreateCommand();
                command.CommandText = BatchConstants.PeakResultsInsert;
    
                string[] parameterNames = new[]
                                     {
                                       "@Id",
                                       "@PeakID",
                                       "@QuanPeakID",
                                       "@ISTDRetentionTimeDiff"
                                      };
    
                DbParameter[] parameters = parameterNames.Select(pn =>
                {
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = pn;
                    command.Parameters.Add(parameter);
                    return parameter;
                }).ToArray();
    
                foreach (var peakResult in peakResults)
                {
                    parameters[0].Value = peakResult.Id;
                    parameters[1].Value = peakResult.PeakID;
                    parameters[2].Value = peakResult.QuanPeakID;
                    parameters[3].Value = peakResult.ISTDRetentionTimeDiff;
    
                    command.ExecuteNonQuery();
                }
    

В итоге я не могу использовать Dapper для вставки в свои большие таблицы.(Для своих маленьких таблиц я все еще использую Dapper).

Обратите внимание, что я нашел еще кое-что:

  • Я пытался использовать несколько потоков для вставки данных в одинбазы данных, это не сделало никакого улучшения.(не имеет значения)

  • Обновлен с System.Data.Sqlite с 1.0.69 до 1.0.79.(ничего не изменилось в производительности, которую я мог видеть)

  • Я не назначаю тип для DbParameter, похоже, в любом случае разница в производительности не имеет значения.

  • Для чтения я не смог улучшить производительность Dapper.

0 голосов
/ 25 января 2012

В настоящее время я обертываю вставки внутри транзакции, чтобы сделать их быстрее (это дало хорошее улучшение).

Наибольший выигрыш, который я видел в объемной скорости вставки, заключался в разбиении вставок на более мелкие куски. Я уверен, насколько маленький размер зависит от платформы / схемы / и т. Д. Я считаю, что во время моих испытаний это было около 1000 или около того.

...