使用IN子句问题更新语句

时间:2010-03-03 16:14:58

标签: sql performance db2 sql-update

我有一个更新声明:

update tableA 
    set val1='X', val2='Y' 

where id in (
    select id from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY')

现在,内部SELECT语句在10分钟内运行,返回1000条记录(tableA和tableB各有大约10mil记录)

整个更新语句运行3个小时(尚未等待完成)

有什么想法吗?

6 个答案:

答案 0 :(得分:2)

tableA.id上可能没有索引,或者tableA.id的类型与select返回的类型不匹配。

[编辑]或者,您可以尝试这种奇怪的语法:

update (
    select val1, val2 from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY'
) tmp
set val1='X', val2='Y' 

这会创建一个仍然链接到原始表的临时表,因此您可以更新select返回的值,它们将显示在原始表中。

[EDIT2]我错过了您选择并更新同一个表格的事实(即id是同一列)。在这种情况下,类型显然无关紧要,您甚至不需要索引(因为select已经返回正确的行)。

尝试EXPLAIN PLAN查看是否还有其他内容。

此外,您可能会与另一个同时更新同一个表的进程发生冲突(即您在某处有锁)。 AQT有一个可以显示这些内容的监视器。如果可以,请获取AQT并使用它。它对DB2有很好的支持,并且比我迄今为止看到的任何东西都要好。

答案 1 :(得分:2)

我知道这个帖子有点旧,但我想分享发生在我身上的事情(特别是今天嘿嘿)。

我们遇到了同样的问题。更新正在永远运行! 因此我们发现我们尝试更新的表已被锁定。但是,DB2没有抛出任何错误消息。

希望我以某种方式帮助过! 干杯。 〜chamb〜

答案 2 :(得分:0)

我过去已经成功打破了子查询,并将其输出存储到临时表中。 e.g。

CREATE TEMPORARY TABLE my_ids (id INT);

INSERT INTO my_ids select id from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY';

update tableA 
    set val1='X', val2='Y' 
WHERE id IN (SELECT id FROM my_ids);

如果您的特定SQL风格具有某种UPDATE JOIN-esque语法(例如UPDATE tableA USING my_ids),那么也可能值得尝试

答案 3 :(得分:0)

您是否在任何列上都有索引?如果tableA.col1,tableB.col1,tableA.col2,tableB.col2,tableA.col3和tableB.col3上没有索引,则可以解释长搜索时间。如果您没有这些比较的索引,您将被迫扫描整个表格,这将很慢。

此外,即使您有索引,也应检查您的统计信息是否是最新的;如果它们不存在,即使索引的物理结构不合适也可能导致问题。

您没有提到您正在使用的数据库,但是如果您有办法让它告诉您查询的执行计划,您可以使用它来确定它正在做什么并采取适当的措施来添加你需要的索引。

答案 4 :(得分:0)

您应该尝试更新加入,因为这样可以改进解释计划。

update tableA A, tableB B
set A.val1='X', A.val2='Y' 
where A.col1 = B.col1 and A.col2 = B.col2
  and A.col3 = 'xx' and B.col3 = 'YY'

索引显然会有助于此次加入,正如其他人已经说过的那样。如果您希望我们检查索引是否正在使用,请复制EXPLAIN结果。

答案 5 :(得分:0)

其他人建议使用EXPLAIN来帮助确定查询速度慢的地方,这当然是个好主意。

另一个建议,虽然您没有说明您正在使用的DB2版本,或者它所使用的平台:

您可能希望尝试使用MERGE语句,这是用于更新连接的A​​NSI SQL语句(自V8.2起,这在DB2 for Linux / Unix / Windows中可用):

合并声明看起来像(未经测试):

merge into tableA a
   using (select id, col1, col2 from tableB where col3 = 'YY') as b
   on (a.col1 = b.col1 and a.col2 = b.col2 and a.col3 = 'xx')
   when matched 
   then update set val1 = 'X', val2 = 'Y'