SQL Server и SqlDataReader - триллион записей - память

"Усеченный не регистрируется, что-либо" корректно. Я пошел бы далее:

Усеченный не выполняется в контексте транзакции.

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

Однако я видел усеченный неумышленно повреждать ссылочную целостность и нарушать другие ограничения. Власть, которую Вы получаете путем изменения данных вне транзакции, должна быть сбалансирована относительно ответственности, которую Вы наследовали при обходе натянутого каната без сети.

6
задан BuddyJoe 6 December 2009 в 19:26
поделиться

3 ответа

Да, это будет потоковая передача ... но я не думаю, что вы действительно должен попытаться это сделать.

Если бы вы могли читать миллион записей в секунду (что кажется мне маловероятным), вам все равно понадобилось бы 12 дней, чтобы прочитать триллион записей ... это большая работа, чтобы рискнуть потерять половину

Теперь я понимаю, что вы, вероятно, действительно не хотите читать триллион записей буквально, но я хочу сказать, что если вы все равно можете разделить свой «большой объем» работы на логические партии , наверное, хорошая идея.

10
ответ дан 8 December 2019 в 04:52
поделиться

Есть несколько деталей.

  • SqlDataReader обычно читает всю строку в памяти и кэширует ее. Сюда входят любые поля BLOB, поэтому вы можете в конечном итоге кэшировать несколько полей размером 2 ГБ в памяти (XML, VARBINARY (MAX), VARCHAR (MAX), NVARCHAR (MAX)). Если такие поля вызывают беспокойство, вы должны передать от CommandBehavior.SequentialAccess до ExecuteReader и использовать возможности потоковой передачи конкретных типов SqlClient, таких как SqlBytes.Stream .

  • Соединение занято до завершения SqlDataReader. Это создает транзакционные проблемы, потому что вы не сможете выполнить какую-либо обработку в базе данных в той же транзакции, потому что соединение занято. Попытка открыть другое соединение и зарегистрироваться в той же транзакции не удастся, поскольку распределенные транзакции с обратной связью запрещены. Необходимо использовать MARS . Для этого нужно установить для соединения MultipleActiveResultSets = True . Это позволяет вам выполнять команду на том же соединении, пока устройство чтения данных все еще активно (типичный цикл fetch-process-fetch). Внимательно прочтите ссылку на Christian Kleinerman's, убедитесь, что вы понимаете проблемы и ограничения, связанные с MARS и транзакциями, они довольно тонкие и нелогичные.

  • Длительная обработка на клиенте блокирует сервер. Ваш запрос по-прежнему будет выполняться все это время, и серверу придется приостановить его, когда канал связи заполнится. Запрос потребляет воркера (или больше, если у него есть параллельные планы), а рабочие очень дефицитный товар на сервере (они примерно приравниваются к потокам). У вас не будет лишних денег, чтобы позволить многим клиентам обрабатывать огромные наборы результатов в свое свободное время.

  • Размер транзакции. Обработка триллиона записей за одну транзакцию никогда не сработает. Журнал должен будет увеличиваться, чтобы вместить всю транзакцию, без усечения и повторного использования VLF, что приведет к огромному увеличению журнала.

  • Время восстановления. Если обработка 999-миллиардной записи завершится неудачно, ей придется откатить всю проделанную работу, поэтому на откат уйдет еще «12» дней.

13
ответ дан 8 December 2019 в 04:52
поделиться

Да, это может занять некоторое время (если ваш SQL не делает ничего глупого, пытаясь сделать снимок или что-то еще), но если ваш сервер может передавать его в потоковом режиме, SqlDataReader не должен нет проблем с использованием памяти.

1
ответ дан 8 December 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: