sql - 优化sql更新语法而不是服务器

标签 sql oracle optimization oracle11g query-optimization

有两个表,一个根据第二个表进行更新。 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)

enter image description here

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/

相关文章:

sql - 在聚合函数 SQL Server 中选择 N 行

sql - 在 Sql Server 中创建序列

mysql - 在 MySQL 的列中为某些值添加前导零

SQL 连接只允许每个表中有一个匹配项

C99条件返回值

java - (JDK 1.6 和 ojdbc6.jar)与(JDK 1.5 和 ojdbc14.jar)

sql - 如何根据旧记录插入新记录并使它们不同?

oracle - 通过 DBLink 移动 XML

c++ - gcc优化对具有明显常量变量的循环的影响

optimization - 哪些处理器支持 "Fast Short REP CMPSB and SCASB"