Основываясь на представленной здесь идее, я создал QueuedDataReader
который обертывает ConcurrentQueue
в IDataReader
поэтому я могу передать его в SqlBulkCopy
и «потоковые» данные в базу данных.
Он работает нормально и довольно быстро, но файл журнала растет довольно резко, хотя я считаю, что я реализовал все предлагаемое здесь здесь (и множество других мест).
Две, возможно, важные детали:
Task
за таблицу) IDENTITY
(которые SqlBulkCopy не вставляет), поэтому я не думаю, что оговорки «SORT» являются релевантными. В дополнение к этому:
SqlBulkCopyOptions.TableLock
Вопрос:
На время написания моего вопроса, я обнаружил еще один отличный ресурс здесь , который указал на BATCHSIZE в качестве потенциального виновника.
Результаты довольно удивительны. Если мы используем параметр BatchSize, производительность становится все хуже и хуже, поскольку мы устанавливаем ее на более низкие значения.
Используя очень маленькое значение для размера партии, пропускная способность сети остается на уровне 20% от общего использования для всего процесса (обратите внимание, что верхний предел размера 500 партий партии равен 25%, что отличается от других графиков). Любое значение ниже 10.000 снижает производительность очень тяжело, что приводит к очень плохому времени и большому использованию файла журнала.
Когда мы достигаем 10.000 размера партии, тогда разница во времени между различными тестами становится очень маленькой. Но, поскольку у нас есть 8 потоков, которые записывают 750 000 строк каждый, тогда у нас есть только 75 кусков данных, отправленных из каждого потока. Излишне говорить, что лучшая производительность достигается, когда мы используем 0 в качестве BatchSize, отправляя целые 750 000 строк в одну партию.
Было бы интересно узнать, есть ли какие-либо выгоды, помимо производительности, с помощью параметра BatchSize. Мы не нашли ничего, что упоминалось в «Книгах On Line», и мы никогда не видели ничего интересного во время нашего опыта, и это говорит нам о том, что лучше всего делать с BatchSize - это оставить его равным нулю, что является его значением по умолчанию, поскольку любое значение, отличное от этого, приведет к снижению производительности процесса загрузки.
Я ранее отказался от BatchSize = 0
из-за ошибок таймаута, но, установив мой BulkCopyTimeout
равным нулю, я получаю некоторый рост файла журнала, но намного меньше, чем раньше.
ОБНОВЛЕНИЕ . После слишком долгого рутинного тестирования я наконец спустился вниз, чтобы написать автоматизированный набор тестов, попробовать варианты BatchSize (0-5000), ставки очереди и кластерные / некластеризованные индексы. (В моем случае я пишу данные в десятки таблиц параллельно).
Это то, что я нашел:
CLUSTERED
или BatchSize равны нулю, я не получаю никакого роста файла журнала. CLUSTERED
все еще предотвращает рост журнала, независимо от BatchSize. Обратите внимание: мои тесты записывают данные с заданной скоростью в очередь, завернутую в IDataReader, которая выгружается BulkInsert. Одна очередь / BulkInsert для каждой таблицы. Следующий шаг - попробовать с большими наборами данных.