Я бы прокомментировал @DanMenes (спасибо за вдохновение), но для справки я добавляю его как отдельный ответ.
Я разработал решение в .NET , которое открывает канал (фактически 2, первый разрушается, как сказал @DanMenes), подготавливает поток данных к нему и затем запускает BULK INSERT
с автоматически сгенерированным файлом формата.
Предпосылка в том, что я могу делать такие вещи, как
var inMemoryData = new[] {
new[] { "val1", "val2" },
new[] { "val3", "val4" },
};
using (var importer = new Importer(SqlConnection, "MyTable", "Col1", "Col2"))
{
importer.Import(inMemoryData);
}
Я подведу итог реализации Importer:
1. Создать трубу
var stream = new NamedPipeServerStream(name, PipeDirection.Out, 2, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
stream.BeginWaitForConnection(OnConnection, this);
2. Принимаю соединения
public void OnConnection(IAsyncResult asyncResult)
{
Stream.EndWaitForConnection(asyncResult);
var buffer = Encoding.UTF8.GetBytes(data);
Stream.Write(buffer, 0, buffer.Length);
Stream.Close();
}
3. Начать BULK INSERT
var insertCommand = DbConnection.CreateCommand();
insertCommand.CommandText = "BULK INSERT [MyTable] FROM '\\.\pipe\mypipe' WITH (FORMATFILE='c:\path\to\formatfile')";
insertCommand.ExecuteNonQuery();
Подробнее см. проект GitHub .
Примечание. Я еще не добавил тесты производительности в проект, но предварительные тесты показали увеличение производительности в 2–5 раз по сравнению с транзакциями INSERTs
.