Повысить производительность объемных вставок SQLite с использованием Dapper ORM

.net dapper sqlite

Вопрос

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

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

    Источник данных = Batch.db; Version = 3; Pooling = True; Max Pool Size = 10; Synchronous = off; FailIfMissing = True; Journal Mode = Off;

  • Я использую 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 тыс. В / сек)
  • 10 000 строк в таблицу с 63 столбцами: 2,74 с для вставки (3,7 тыс. / Сек)

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

Принятый ответ

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

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

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

  • 55 000 строк (19 столбцов) в 0,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.


Популярные ответы

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

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



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему