有两个表,一个根据第二个表进行更新。 SQL 正在工作,但我认为由于记录数量的原因,它花费了太多时间。请参阅this fiddle 。实际主表包含1,500,000条记录,子表包含700,000条记录,下面的sql持续执行了4个小时,因此终止。
UPDATE master m SET m.amnt = (SELECT amnt FROM child c WHERE c.seqn = m.seqn)
WHERE m.seqn IN (SELECT seqn FROM child);
这条sql的执行计划是(红色的是master,其他的是child)
seqn
是主键。毫无疑问,这一切都取决于服务器的性能和索引的统计数据。然而,令我困扰的是,索引没有访问 master,而 child 被读取了两次。 sql有可能被优化,但oracle决定这样做,但是我尝试将sql优化为
UPDATE (
SELECT m.seqn m_seqn,c.seqn c_seqn, c.amnt c_amnt, m.amnt m_amnt
FROM master m INNER JOIN child c ON m.seqn = c.seqn)
SET m_amnt = c_amnt
导致以下错误
ORA-01779: cannot modify a column which maps to a non key-preserved
table : UPDATE ( SELECT m.seqn m_seqn,c.seqn c_seqn, c.amnt c_amnt, m.amnt m_amnt
FROM master m INNER JOIN child c ON m.seqn = c.seqn) SET m_amnt = c_amnt
除了更新统计信息和调整服务器之外,还有什么方法可以优化 SQL?
编辑如果要加入的列不是 PK,@Sebas 的解决方案将不起作用
最佳答案
看看这个:
UPDATE
(
SELECT m.amnt AS tochange, c.amnt AS newvalue
FROM child c
JOIN master m ON c.seqn = m.seqn
) t
SET t.tochange = t.newvalue;
SELECT * FROM master;
fiddle :http://www.sqlfiddle.com/#!4/c6b73/2
你刚刚错过了 fiddle PK。
关于sql - 优化sql更新语法而不是服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19921656/