Для этого вам необходимо использовать SSIS.
Вам нужно немного узнать о том, как работают поставщики данных ADO.Net, чтобы понять, что вы можете делать, и что вы не можете сделать. Например, возьмите поставщика. Верно, что асинхронно выполнять запросы с BeginExecuteReader
, но это асинхронное выполнение выполняется до тех пор, пока запрос не начнет возвращать результаты. На уровне проводки текст SQL отправляется на сервер, сервер начинает опрокидывать выполнение запроса и в конечном итоге начнет толкать строки результатов обратно клиенту. Как только первый пакет возвращается клиенту, выполняется асинхронное выполнение и выполняется обратный вызов завершения. После этого клиент использует метод SqlDataReader.Read
()
для продвижения набора результатов. В SqlDataReader нет асинхронных методов. Эта модель работает с запросами на сложные запросы, которые возвращают мало результатов после того, как будет выполнена серьезная обработка. Пока сервер занят производством результата, клиент простаивает без блокировки потоков. Однако для простых запросов, которые производят большие результирующие наборы (как вам кажется), все совершенно по-другому: сервер будет немедленно производить обновления и будет продолжать возвращать их клиенту. Асинхронный обратный вызов будет почти мгновенным, и основная часть времени будет потрачена клиентом, итератором по SqlDataReader.
Вы говорите, что думаете о размещении записей в очереди памяти в первую очередь. Какова цель очереди? Если обработка алгоритма медленнее, чем пропускная способность результирующего набора результатов DataReader, то эта очередь начнет нарастать. Он будет потреблять живую память и, в конечном итоге, будет исчерпывать память на клиенте. Чтобы этого не произошло, вам нужно будет построить механизм управления потоком, т. Е. если размер очереди больше N, не помещайте в него больше записей. Но для этого вам придется приостановить итерацию чтения данных, и если вы сделаете это, вы нажмете управление потоком на сервер, который приостановит запрос до тех пор, пока канал связи не будет доступен снова (пока вы не начнете читать с читателя). В конечном счете, управление потоком необходимо прокладывать до сервера, что всегда имеет место в любом соотношении производителей и потребителей, продюсер должен остановиться, иначе промежуточные очереди заполняются. Ваша очередь в очереди не имеет никакой цели, кроме усложнения. Вы можете просто обрабатывать элементы из считывателя по одному, и если скорость обработки слишком медленная, считыватель данных будет применять управление потоком в запросе, запущенном на сервере.Это происходит автоматически, потому что вы не вызываете метод DataReader.Read.
Чтобы подвести итог, для обработки большого набора вы не можете выполнять асинхронную обработку, и нет необходимости в очереди.
Теперь сложная часть.
Является ли ваша обработка любой вид обновления в базе данных? Если да, то у вас есть гораздо большие проблемы:
- Вы не можете использовать то же соединение для записи результата, потому что оно занято устройством чтения данных. SqlClient для SQL Server поддерживает MARS, но это решает проблему только с SQL 2005/2008.
- Если вы собираетесь регистрировать чтение и обновление в транзакции, если ваши обновления происходят в другом соединении (см. Выше), то это означает использование распределенных транзакций (даже если оба конэнцитона связаны с одним и тем же сервером) , Распределенные транзакции медленны.
- Вам нужно будет разделить обработку на несколько партий, потому что очень плохо обрабатывать записи 1B + в одной транзакции. Это также означает, что вы должны будете иметь возможность возобновить обработку прерывистой партии, что означает, что вы должны иметь возможность идентифицировать записи, которые уже были обработаны (если обработка не является идемпотентной).
* Этот ответ заслуживает большего количества голосов! * – JohnB