Прочитайте 5 миллионов записей и, наконец, обновите столбец



Я должен обновить 5 миллионов+ записей в базе данных для таблицы T1. Это C# tool, который будет READ (Select) столбец в таблице T1, скажем, T1.col1, затем извлекает значение на основе логики из этого столбца и, наконец, должен UPDATE другой столбец T1.col2 в той же таблице с этим обработанным значением и обновить БД.



Хотел бы получить некоторые мнения о наилучшем / оптимизированном способе достижения этой цели в C# / ADO.NET ?




Примечание: логика извлечения не может быть частью SQL. Такая логика есть
встроенный в COM DLL, который я взаимодействую с .NET и применяю на
значение столбца Col1 для генерации нового значения, которое должно быть окончательно сохранено в T1.И col2.


616   7  

7 ответов:

Поскольку вам нужно передать данные tha для некоторой операции COM-объектом, это то, что я бы сделал:

Используйте машину с большим объемом памяти-загружайте данные кусками (например, 5000 или 50000 строк одновременно) в память, обрабатывайте их и выполняйте обновление на SQL Server...

Для части обновления используйте транзакции и поместите 5000-20000 обновлений в одну транзакцию...

[EDIT] : путем правильного разбиения работы и присвоения для 500000 или 1000000 строк одному "рабочая машина" вы можете ускорить это до максимального предела вашего SQL-сервера... [/EDIT]

Другой вариант-хотя и не рекомендуется (только из-за теоретически возможных проблем безопасности и/или стабильности, введенных COM-объектом в этом конкретном случае):

хотя это описание относительно SQL Server, что-то подобное возможно и с Oracle на Windows

Вы можете поместить логику этого преобразования в свой SQL-сервер с помощью Запись+Установка сборки .NET, которая предоставляет хранимую процедуру, которую можно вызвать для выполнения преобразования... .NET-сборка, в свою очередь, получает доступ к этому COM-объекту... для как посмотреть http://www.sqlteam.com/article/writing-clr-stored-procedures-in-charp-introduction-to-charp-part-1

Ссылка MSDN на это http://msdn.microsoft.com/en-us/library/ms131094.aspx

Безусловно, самый быстрыйспособ-это выполнить обновление в самом коде SQL:

UPDATE T1
SET col2 = [some function based on col1]

(имейте в виду, что в зависимости от платформы базы данных это может привести к разрыву журнала транзакций. Для MS SQL, в частности, я бы рекомендовал вам обновлять меньшими партиями, возможно, 100k строк или меньше за один раз)

Если логика функции слишком запутана для этого, то убедитесь, что вы выпускаете все свои 5 миллионов обновлений на основе первичного ключа:

UPDATE T1
SET col2 = @newval
WHERE tableID = @id

Действительно ли вам нужно обновить col2 с новым значением?

Если каждая строка получает значение smmae, я запишу его в отдельную таблицу с 1 строкой и просто перекрестно соединю эту строку, когда вам нужно будет вернуть результат.

Вот так:

update t2 
set col2 = 1234 -- the computed value over all rows in t1

select t1.col1, 
       t2.col2 
from   t1
       cross join t2 -- t2 only has 1 row
Обновления относительно дороги, и написание 1 строки, безусловно, намного дешевле, чем написание 5 миллионов.

Иначе я бы поставил мельницу там, где древесина, поэтому используйте TSQL, если это возможно. Опять же 5 миллионов - это не так уж и много. проблема, вы можете обрабатывать их на сервере или вам нужно перетащить их через сеть? В последнем случае все сходится.

Ргдс Герт-Ян

Это много данных, чтобы иметь в памяти все сразу. Я бы рекомендовал по возможности извлекать данные в виде небольших пакетов записей из библиотеки DLL COM и обрабатывать их. Использование PLinq для объектов позволит вам максимально использовать процессор. Между этими двумя Вы должны быть в состоянии найти золотую середину, которая хорошо работает.

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

Таким образом, в зависимости от требований, параметры было бы:

1) Запустите отдельный поток (или даже несколько потоков) для выполнения обновлений, в то время как основной поток вернет пользователю что-то вроде "длительная операция выполняется". Пожалуйста, вернитесь на эту страницу позже, чтобы увидеть его статус "

2) запускайте обновления каждую ночь в отдельном процессе

3) реорганизовать проект таким образом, чтобы можно было позволить выполнять обновления в базе данных.

Обновить

Я вижу, что вы постоянно говорите, что не можете перенести свой обновите логику в базе данных. Если вы не отвечаете за архитектуру проекта, не могли бы вы повлиять на руководство, чтобы реорганизовать весь материал? Это выглядит как плохая архитектура, если такие операции необходимы.

Некоторые основные указатели:

  1. Используйте DataReader, а не DataSet. Накладные расходы памяти набора данных, вероятно, создадут проблемы с таким количеством строк
  2. Если возможно, выполните вычислительную часть в нескольких потоках параллельно. Вы можете сделать это с помощью TPL для этого, но поскольку вы используете компонент COM, могут возникнуть некоторые проблемы с доступом к нему из нескольких потоков. Проконсультируйтесь с экспертом COM (или откройте другой вопрос SO) о том, как определить, является ли ваш COM компонент потокобезопасен.
  3. Не держите ни одной массивной транзакции открытой при вычислении результата. Используйте подсказку " with (nolock)", если это соответствует вашей семантике. Это поможет предотвратить влияние ваших задач на других читателей / авторов.

Если это одноразовая сделка, то сбросьте свои 5 миллионов + записей в файл. Запустите логику для файла, чтобы сгенерировать новые записи. Логика дампа и файла должна быть быстрой и не отнимать много времени. Затем массово вставьте обновленные данные в промежуточную таблицу.

В этот момент откажитесь от предыдущей таблицы и сделайте промежуточную таблицу реальной таблицей с некоторыми операторами DDL, чтобы поместить в соответствующие индексы, FKs и т. д.

Это был бы самый быстрый способ справиться с этой суммой. из записей. Что-нибудь еще, и это, вероятно, займет по крайней мере несколько дней, чтобы обработать все.

Comments

    Ничего не найдено.