Должен ли я использовать SqlBulkCopy или хранимую процедуру для импорта данных

У меня есть файл журнала размером 248 МБ, который может увеличиваться до ГБ. Итак, вы можете себе представить, сколько строк может быть. Мне нужно импортировать все строки в таблицу в базе данных SQL Server. Для этого я сначала создаю DataTable и добавляю все строки в файле журнала в этот DataTable как новые строки. Это происходит довольно быстро. Примерно за 30 секунд в таблицу добавляется более миллиона записей. После того, как таблица заполнена строками, я импортирую записи в DataTable в базу данных, используя хранимую процедуру. Однако эта фаза выполняется очень тяжело. Теперь мне интересно, следует ли мне вместо этого использовать метод SqlBulkCopy WriteToServer или мне следует придерживаться этого пути? Если SqlBulkCopy является лучшим выбором, следует ли использовать версию DataTable или IDataReader. Заранее спасибо.


person Mikayil Abdullayev    schedule 23.01.2012    source источник


Ответы (1)


Я бы использовал SqlBulkCopy для импорта данных любого реального объема, подобного этому. Разница в производительности по сравнению с SqlDataAdapter может быть большой. например Я записал в блог для сравнения производительности для импорта 100 тыс. строк:

SqlBulkCopy: 1,5885 с
SqlDataAdapter: 25,0729 с

Вы можете получить еще большую пропускную способность, если используете параметр TableLock с SqlBulkCopy, который в моем тесте сократил импорт до 0,8229 с.

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

person AdaTheDev    schedule 23.01.2012
comment
Поскольку вы много практиковались с SqlBulkCopy, вы, возможно, знаете, почему у меня истекает время ожидания. Время ожидания истекло до завершения... ошибка. Я увеличил время ожидания соединения до 600 секунд. Но я получаю ошибку менее чем за полминуты. - person Mikayil Abdullayev; 23.01.2012
comment
Попробуйте установить BulkCopyTimeout для SqlBulkCopy (в секундах): msdn.microsoft.com/en-us/library/ - person AdaTheDev; 23.01.2012
comment
Большое спасибо @AdaTheDev. Вы сэкономили мне кучу времени - person Mikayil Abdullayev; 23.01.2012
comment
@Mikayil - рад, что смог помочь! - person AdaTheDev; 23.01.2012
comment
@AdaTheDev Итак, ваш ответ и сообщение в блоге сравнивают SqlBulkCopy и серию операторов вставки через SqlDataAdapter, но как насчет хранимой процедуры? Я могу отправить таблицу данных как пользовательский тип и выполнить SELECT FROM INTO (или INSERT INTO FROM, я всегда получаю эти два в обратном порядке). В этот момент я выполняю вставку как единую операцию набора SQL. SqlBulkCopy по-прежнему лучше, и если да, то почему? - person Ari Roth; 01.08.2018
comment
@AriRoth Эй, так что у вас есть дополнительные параметры с SqlBulkCopy для дальнейшего ускорения массовой вставки (т. Е. Разделить данные на фрагменты и импортировать параллельно). У меня был последующий пост, связанный с этим оригиналом, в котором говорилось об этом. Лучше субъективно, так как это зависит от сценария, т.е. для меньшего количества строк я бы, вероятно, выбрал TVP. Для большего размера я бы использовал SqlBulkCopy и объединил их в БД. ХТН. - person AdaTheDev; 01.08.2018
comment
@AdaTheDev Я отказываюсь от строки, мучительно вставляя строку (загрузка CSV), и хочу перейти к эффективному решению, такому как TVP или SQLBulkCopy. Я склоняюсь к TVP, поскольку в моем проекте используются хранимые процедуры (проще переход), но когда вы упоминаете, что «меньшее количество строк идет с TVP», что это за «меньшее число»? Пока у меня 200 тыс. строк, но потенциально может вырасти до 500 тыс. Макс. Я также планирую использовать хранимые процедуры в любом случае, чтобы предоставить пользователям обратную связь о том, почему их данные не работают (из-за опечаток данных) - person AVu; 12.02.2021
comment
@AVu - в прошлом году я написал об этом обновленный пост в блоге со сравнением различных объемов строк, а также многопоточного и однопоточного: sentryone.com/blog/ - person AdaTheDev; 13.02.2021