SQL Server и SqlDataReader - триллион записей - память - PullRequest
6 голосов
/ 04 декабря 2009

Я никогда не пробовал этого - поэтому я не знаю, столкнусь ли я с проблемами с памятью.

Но может ли SqlDataReader прочитать триллион записей? Это все течет правильно? Я немного неравнодушен к тому, что делает протокол SQL / TDS под прикрытием.

UPDATE Перевести триллион, чтобы означать очень большое число. Я, наверное, должен был сказать что-то вроде 1 миллиарда или 100 миллионов.

Ответы [ 3 ]

13 голосов
/ 04 декабря 2009

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

  • 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 дней.

10 голосов
/ 04 декабря 2009

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

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

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

1 голос
/ 04 декабря 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...