首先,我知道使用table_a
中的值更新table_b
的sql语句采用以下形式:
甲骨文:
UPDATE table_a
SET (col1, col2) = (SELECT cola, colb
FROM table_b
WHERE table_a.key = table_b.key)
WHERE EXISTS (SELECT *
FROM table_b
WHERE table_a.key = table_b.key)
MySQL的:
UPDATE table_a
INNER JOIN table_b ON table_a.key = table_b.key
SET table_a.col1 = table_b.cola,
table_a.col2 = table_b.colb
据我所知,数据库引擎将遍历table_a
中的记录,并使用table_b
中匹配记录的值更新它们。
因此,如果table_a
中有1千万条记录,table_b
中只有10条记录:
这是否意味着引擎将通过table_a
进行1000万次迭代只更新10条记录? Oracle / MySQL / etc是否足够聪明,只能通过table_b
进行10次迭代?
有没有办法强制引擎实际迭代table_b
而不是table_a
中的记录来进行更新?是否有sql语句的替代语法?
假设table_a.key
和table_b.key
被编入索引。
答案 0 :(得分:3)
基于表b中只有十行的事实,任何一个引擎都应该足够聪明以优化查询。引擎如何确定要做的是基于索引和统计等因素。
如果“key”列是主键和/或已编制索引,则引擎必须执行很少的工作才能运行此查询。它基本上已经是“知道”匹配行的位置,并且非常快速地查找它们。它根本不需要“迭代”。
如果键列上没有索引,引擎将不得不进行“表扫描”(大致相当于“迭代”)以找到正确的值并匹配它们。这意味着它必须扫描1000万行。
对所谓的执行计划进行一些阅读。这基本上解释了引擎为了运行查询而必须做的工作(一些数据库仅在文本中显示,有些数据库可以选择以图形方式查看)。学习如何解释执行计划将使您深入了解如何向表中添加索引并优化查询。
如果它们不起作用(这已经有一段时间了),请查看这些内容,但它类似于:
我认为第一个(Oracle)查询最好使用JOIN而不是WHERE EXISTS编写。引擎可能足够智能,无论哪种方式都能正确优化。一旦掌握了执行计划的解释,您就可以双向运行并亲眼看看。 :)
答案 1 :(得分:1)
好的,我知道回答自己的问题通常是不满意的,但我已经接受了另一个答案,并且不会接受它,所以在这里它就是......
我发现了一个更好的选择,我想与遇到相同场景的任何人分享:MERGE
声明。
显然,较新的Oracle版本引入了这个MERGE
声明,这个声明很简单!在大多数情况下,不仅性能好得多,语法也很简单,因此使用UPDATE
语句让我觉得很愚蠢!来了..
MERGE INTO table_a
USING table_b
ON (table_a.key = table_b.key)
WHEN MATCHED THEN UPDATE SET
table_a.col1 = table_b.cola,
table_a.col2 = table_b.colb;
当INSERT
没有table_a
中某些记录的匹配记录时,我还可以扩展声明以包含table_b
操作:
MERGE INTO table_a
USING table_b
ON (table_a.key = table_b.key)
WHEN MATCHED THEN UPDATE SET
table_a.col1 = table_b.cola,
table_a.col2 = table_b.colb
WHEN NOT MATCHED THEN INSERT
(key, col1, col2)
VALUES (table_b.key, table_b.cola, table_b.colb);
这个新的声明类型让我在发现它的那一天:)