2010-03-03 115 views
2

我有一个更新语句去这样的: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条记录运行(包括表A和tableB的有关于10MIL记录每个)

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

任何想法?

+0

它可能为tableA中的每一行运行内部查询。你使用的是哪个数据库? – 2010-03-03 16:18:41

+0

数据库是DB2 – Peter 2010-03-03 16:23:00

+0

表A上是否有涉及修改列的索引?开销可能会减慢进程 – 2010-03-03 16:24:41

回答

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' 

这将创建仍链接到原始表的临时表,所以你可以更新其数值的选择回报,他们将出现在原始表格中。

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

尝试EXPLAIN PLAN看看是否有其他事情正在发生。

此外,您可能在与另一个进程,这也更新了同桌冲突得到(即你有地方的锁)。 AQT有一个显示器可以显示这些东西。如果可以的话,获得AQT并使用它。它对DB2有着出色的支持,比迄今为止我看到的更好。

+1

这是同一张桌子上的同一列...不知道它如何与类型不匹配... – 2010-03-03 16:19:59

+1

+1 - 良好的通话。另外,您可以尝试对查询进行EXPLAIN。 – 2010-03-03 16:20:27

+1

tableA.id上有一个索引 我不认为tableA.id问题的类型在这里是有效的。 – Peter 2010-03-03 16:20:49

0

我已经在过去的成功与突破的子查询出来,并存储其输出到一个临时表。例如

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味道已经某种更新JOIN式的语法(如UPDATE TABLEA使用my_ids)也可能是值得尝试

+0

这确实是一个解决方案,但这是一个日常的批处理作业,DBA对于创建这些临时表并不酷。 – Peter 2010-03-03 16:24:07

+0

您可以使用全局临时表,这些临时表只有在声明它们的应用程序结束其与数据库的连接之后才存在。 – 2010-03-04 00:20:56

0

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

而且,即使你有,你应该检查,看看你的统计数据是最新的指标;如果它们不是,那么即使索引的物理结构很好,也会导致问题。

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

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结果。

+0

DB2中不支持此语法。 – 2010-03-04 00:19:44

+0

我写这个时没有指定DB2。 – 2010-03-04 07:25:35

0

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

另外一个建议,虽然uou不要说你正在使用的DB2版本,或者是什么平台,它是:

您可能需要使用MERGE语句,这是ANSI SQL语句来尝试的更新加入(这已在自V8.2 DB2用于Linux/UNIX/Windows的是可利用):

MERGE语句看起来是这样的(未测试):

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' 
2

我知道这个线程有点老,但我喜欢分享发生在我身上的事情(具体的今天盟友今天呵呵)。

我们正面临同样的问题。更新永远在运行! 所以我们发现我们试图更新的表被锁定了。但是,DB2没有引发错误消息。

希望Ive帮助过某种程度! 欢呼声。 〜chamb〜