Я работаю над средством импорта, которое генерирует данные, которые необходимо поместить в базу данных SQL Azure (настроенную как бессерверную с 4 виртуальными ядрами).
Объекты, которые я вставляю, имеют всего несколько столбцов.
Id : INT
Type : NVARCHAR
Uid : NVARCHAR
Json : NVARCHAR
Данные Json
в среднем имеют размер около 1,5 КБ. Я импортирую около 3 миллионов строк за прогон.
Мой текущий подход заключается в использовании одной транзакции на 2000 вставляемых строк (отрывок кода ниже):
using var transaction = sqlConnection.BeginTransaction (System.Data.IsolationLevel.ReadUncommitted);
cmd = new SqlCommand (insertNodeQuery, sqlConnection) {
CommandTimeout = 600
};
cmd.Transaction = transaction;
cmd.Parameters.AddWithValue ("@Type", node.Type);
[...]
var insertTask = cmd.ExecuteNonQueryAsync ();
tasks.Add (insertTask);
Затем я использую Task.WhenAll(tasks)
, чтобы дождаться завершения транзакции.
На моем ПК это дает мне 20 вставок в секунду против (localdb)
. Однако в случае с Azure DB я вижу только около 5 вставок в секунду. Я понимаю, что есть сетевая задержка, но даже при запуске кода в центре обработки данных Azure (AKS) в том же регионе я не приближаюсь к скорости локальной БД.
Это заставляет меня задаться вопросом, есть ли лучший способ запуска импорта? Будет ли вариант SqlBulkCopy
, учитывая, что я отправляю сгенерированные данные в памяти в БД?
Как еще можно оптимизировать производительность?
How else can I optimize the performance?
SqlBulkCopy — лучший. Вы можете загрузить DataTable для загрузки данных в памяти или использовать адаптер, например это, для преобразования коллекции объектов в памяти в IDataReader для использования с SqlBulkCopy.
Вы также можете отправить каждый пакет в виде документа JSON в качестве параметра SQL-запроса, где вы читаете его с помощью OPENJSON.
Оба они должны быть быстрее, чем однострочные вставки.
Методы загрузки на стороне клиента в (грубом) порядке от самого медленного к самому быстрому: