Большие SQL-вставки TVF против BULK-вставки

Каков самый быстрый способ вставить огромный массив (10 миллионов элементов) из приложения С#?

До сих пор я использовал объемную вставку. Приложение C# создает большой текстовый файл, и я загружаю его с помощью команды BULK INSERT. Из любопытства я написал простую определяемую пользователем функцию табличного значения CLR.

[SqlFunction(Name = "getArray", FillRowMethodName = "FillRow")]
        public static IEnumerable getArray(String name)
        {
        return my_arrays[name]; // returns the array I want to insert into db
        }

        public static void FillRow(Object o, out SqlDouble sdo)
        {
            sdo = new SqlDouble((double)o);
        }

И этот запрос:

INSERT INTO my_table SELECT data FROM dbo.getArray('x');

Работает почти в 2 раза быстрее объемного аналога. Точные результаты:

BULK - 330с (запись на диск + вставка) TVF - 185с

Конечно, это связано с накладными расходами на запись, но я не знаю, есть ли у BULK-вставки какой-либо эквивалент в памяти.

Итак, мой вопрос - лучше ли TVF по сравнению с BULK (который создан для огромных вставок), или я что-то здесь упускаю. Есть ли какая-то третья альтернатива?


person Klark    schedule 30.06.2011    source источник


Ответы (2)


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

SqlBulkCopy принимает IDataReader, который необходимо реализовать, но только несколько методов интерфейса. Что я всегда делаю, так это просто создаю class MyBulkCopySource : IDataReader, нажимаю «Реализовать интерфейс» и загружаю его в BulkCopy, чтобы увидеть, какой метод вызывается. Реализуйте это, попробуйте еще раз и т. д. Вам нужно реализовать только три из четырех из них, остальные никогда не вызываются.

Насколько я знаю, это самый быстрый способ перекачки данных из программы C # в SqlDB.

GJ

person gjvdkamp    schedule 30.06.2011

  • Использовать SqlBulkCopy
  • Из нескольких потоков с блоками, например, 30 000 строк каждый раз.
  • НЕ за финальный стол, а за временный стол
  • Из которого вы копируете, используя настройку соединения, которая не учитывает блокировки.

Это полностью ставит самую маленькую блокировку на крайний стол.

person TomTom    schedule 30.06.2011
comment
Вы уверены насчет нескольких потоков? Вы имеете в виду несколько SBC, каждый из которых подключен к своему соединению? Обычно я ожидаю, что узким местом будет либо сеть, либо дисковод. Я думаю, что использование нескольких потоков приведет к разногласиям. - person gjvdkamp; 30.06.2011
comment
Несколько потоков, поэтому несколько SBC работают одновременно. Я использую это для загрузки больших объемов данных (600+ миллионов) и удвоил пропускную способность, используя 3 потока. Меньше разногласий там, где это важно — на основном столе. Время блокировки там низкое, и три потока в любом случае используют отдельные экземпляры временной таблицы;) Поддерживает поток данных все время. - person TomTom; 30.06.2011