2009-12-04 3 views
5

Я никогда не пробовал это - так что я не знаю, попаду ли я в проблемы с памятью.SQL Server и SqlDataReader - Trillion Records - Memory

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

ОБНОВЛЕНИЕ Перевести триллион на очень большое количество. Вероятно, я должен был сказать что-то вроде 1 миллиарда или 100 миллионов.

+4

Планируете ли вы прочитать триллион записей? или это просто для интереса? – gbn

ответ

10

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

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

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

+0

Итак, мой первоначальный вопрос должен был стать лучшей стратегией докетирования для ADO.NET и SQL Server ... так что лучший способ заняться 1000 записями за раз. Предположим, вы делаете операцию типа MapReduce. Я понимаю, что для этого есть другие инструменты (Open and Commercial), но если компания, над которой вы работаете, не позволит вам использовать их ... они мне не помогают. (за исключением попыток заимствовать идеи) – BuddyJoe

+0

Хороший вопрос о 12 днях +1. Возможно, я выбрал слишком высокий номер. – BuddyJoe

+0

Если честно, лучшая стратегия дозирования будет зависеть от точной природы задачи. Можете ли вы надежно разбить его на партии, даже если запросы будут запущены позднее? Можете ли вы разбить его на партии раньше времени и дать другим компьютерам разные партии? Есть ли что-нибудь еще, чтобы писать эти данные? Имеются ли соответствующие индексы? В основном это случай разработки способа разделения ваших данных в запрашиваемой и эффективной форме. –

1

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

13

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

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

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

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

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

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

+0

Очень хорошая информация. +1 Какую роль играют транзакции в системе, если данные должны быть в конечном итоге последовательными? Что вы предлагаете - это правильный способ пакетного процесса 1000 или 10000 за раз? (см. комментарии к Jon Skeet) – BuddyJoe

+0

Правильный способ создания пакетов, которые можно безопасно возобновить, зависит от выполняемой задачи. Тривиальный пример - иметь таблицу с «текущим» кластеризованным значением ключа. В транзакции вы получаете значение из таблицы, выбираете следующий порядок строк 10k кластеризованным ключом, обрабатываете их, обновляете текущее значение ключа в таблице, фиксируете. Полоскание, цикл и повторение. –

Смежные вопросы