1

我有一张有 9200 万行的表。我有该表中需要更新数据的 4000 个 ID 的列表。我将 4000 个 ID 放入他们自己的表中并尝试运行以下命令:

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

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

谢谢。

4

2 回答 2

4

虽然可能有办法通过花哨的子选择来用另一个表更新一个表,但我相信最好的方法是使用 SQL API 编写一个程序来执行此操作(无论是用于 perl 的 DBD::DB2 驱动程序的 DBI,用于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 
             )  

编辑: 我实际上很惊讶您提供的查询不适用于 SQL squirrel,因为它是合法查询。它甚至可以执行类似于我给出的示例,因为 DB2 非常擅长优化 SQL/确定最佳访问路径。

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

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

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

于 2011-10-06T16:40:18.973 回答
1

我发布的查询实际上工作正常。我的问题是由使用外部程序查询数据库引起的,而不是使用直接输入查询数据库。对不起,错误的问题。

于 2011-10-07T07:50:50.557 回答