更新db2数据库行的有效方法

时间:2011-10-06 11:17:21

标签: sql db2 memory-efficient

我有一张包含9200万行的表格。我有一个4000表的列表,需要数据更新。我将4000个ID放入他们自己的表中并尝试运行以下内容:

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

但由于内存限制,这会失败。所以我尝试将4000个ID分成4个表,每个表1000个,如果我在那些较小的表上尝试它,它仍然会掉头。什么是处理这么大的桌子最有效的方法?

感谢。

2 个答案:

答案 0 :(得分:4)

虽然可能有方法通过花哨的子选择用另一个表更新表,但我认为最好的方法是使用SQL API编写一个程序来执行此操作(无论是DBI还是DBD :: DB2驱动程序用于perl ,JDBC for Java或C库等)使用游标从RESULTSET执行SELECT,FETCH每个结果行,并进行更新。

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谓词,但可能没有更多的内存或日志空间效率,并且因为它不如select,loop,fetch,update更简单,你需要确保所有条件都正确。你的情况有点简单 - 我认为这会有效,但我需要一个db2实例来反复尝试:

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

修改 我真的很惊讶你提供的查询不能使用SQL squirrel,因为它是一个合法的查询。它甚至可能与我给出的示例类似,因为DB2非常擅长优化SQL /确定最佳访问路径。

在我的回答中,我试图展示更新表的最有效内存方式,以及使用纯SQL从另一个表更新一个表中的行的一般模式(这将涵盖一个表包含更多表的情况)而不仅仅是你想要更新的行)。

此外,我怀疑包含超过20个左右值的IN谓词,即使现代数据库引擎轻松处理它们也是如此。

但是,检查数据库引擎是否有效处理查询和/或比较两个SQL查询的最佳方法是使用SQL explain命令。

答案 1 :(得分:1)

我发布的查询实际上运行正常。我的问题是由使用外部程序查询数据库引起的,与使用直接输入查询数据库相反。对于错误通知的问题,我们深表歉意。