Эффективный способ обновить строки базы данных db2 - PullRequest
1 голос
/ 06 октября 2011

У меня есть таблица с 92 миллионами строк. У меня есть список из 4000 идентификаторов из этой таблицы, которые нуждаются в обновлении данных. Я поместил 4000 идентификаторов в их собственную таблицу и попытался выполнить следующее:

update clients
set col1='1', col2='y'
where id in
(select id from idstoupdate)

Но это падает из-за ограничений памяти. Поэтому я попытался разделить 4000 идентификаторов на 4 таблицы, каждая из которых по 1000, и они все еще падают, если я попробую их на этих меньших таблицах. Какой самый эффективный способ справиться с таким большим столом?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 06 октября 2011

Хотя могут быть способы обновления таблицы другой таблицей с помощью причудливых подвыборов, я считаю, что лучший подход - написать программу для этого с использованием API SQL (будь то DBI с драйвером DBD :: DB2 для perl JDBC для Java или библиотеки C и т. Д.) Для выполнения SELECT, извлечения каждой строки результата из RESULTSET с помощью курсора и обновления.

PSEUDOCODE (я не знаю, на каком языке вы знакомы):

dbHandle = sqllib->open_connection(database, user, password) 
select_statement = dbHandle->prepare('SELECT id FROM idstoupdate')
update_statement = dbHandle->prepare('UPDATE clients SET col1=?, col2=? WHERE ID=?')
resultset = statement->execute(select_statement)

foreach (row in resultset) {
  id = row.getColumn('id')
  update_statement->execute('1','2',id) 
}

dbHandle->disconnect();  

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

содержится множество материалов о том, как сделать все это.

Примечание: Если ваши исходные данные для idstoupdate - это файл, то вы можете пропустить оператор select и ту работу, которую вы делаете, чтобы загрузить таблицу idstoupdate, и просто прочитать файл и обновить базу данных. Это был бы наиболее эффективный способ обработки обновлений таблицы.

Если вам просто нужно обновить таблицу из другой таблицы с использованием чистого SQL, то наиболее распространенными примерами являются следующие:

      UPDATE table1 t1
         SET (t1.field1, t1.field2) = 
             (
               SELECT t2.field1, 
                      t2.field2
                 FROM table2 t2
                WHERE t1.joinfield = t2.joinfield 
                  AND t2.criteriafield = 'qualifier'
             )
       WHERE EXISTS 
             ( 
               SELECT 1 
                 FROM table2
                WHERE t1.joinfield = table2.joinfield 
                  AND t2.criteriafield = 'qualifier'
             )    

, который исключает предикат IN, но, вероятно, не намного эффективнее с точки зрения памяти или пространства журналов, и поскольку он не так прост, как выборка, цикл, выборка, обновление, вы должны быть уверены, что все критерии верны. Ваш случай немного проще - я думаю, что это сработает, но мне нужен экземпляр db2, чтобы попробовать его:

      UPDATE clients t1
         SET t1.col1 = '1', col2 = 'y' 
       WHERE EXISTS 
             ( 
               SELECT 1 
                 FROM idstoupdate t2
                WHERE t1.id = t2.id 
             )  

Edit: Я на самом деле удивлен, что запрос, который вы дали, не работал с SQL-белка, так как это допустимый запрос. Он может даже работать аналогично примеру, который я привел, поскольку DB2 очень хороша в оптимизации SQL / определении наилучшего пути доступа.

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

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

Однако лучший способ проверить, эффективно ли обработчик ваших запросов обрабатывает ядро ​​базы данных и / или сравнить два запроса SQL, - это использовать команды объяснение SQL .

1 голос
/ 07 октября 2011

Отправленный мной запрос на самом деле работает нормально.Моя проблема была вызвана использованием внешней программы для запроса базы данных, в отличие от запроса базы данных с помощью прямого ввода.Извините за неправильно поставленный вопрос.

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