如何加快SQL中的联接更新?我的陈述似乎无限期地发生

Jor*_*mer 2 sql oracle performance

我有两个表:源表和目标表.目标表将包含源表的列的子集.我需要通过基于另一列连接源表来更新目标表中的单个列.更新声明如下:

UPDATE target_table tt
SET special_id = ( SELECT source_special_id
                   FROM source_table st
                   WHERE tt.another_id = st.another_id )
Run Code Online (Sandbox Code Playgroud)

出于某种原因,这种说法似乎无限期地运行.内部选择在自己执行时几乎立即发生.该表有大约50,000条记录,并且托管在一台功能强大的机器上(资源不是问题).

我这样做了吗?上述任何原因都不能及时发挥作用?有更好的方法吗?

Cod*_*rks 7

初始查询对外部表中的每一行执行一次内部子查询.看看Oracle是否更喜欢这样:

UPDATE target_table 
SET special_id = st.source_special_id
FROM 
    target_table tt
    INNER JOIN
    source_table st
        WHERE tt.another_id = st.another_id 
Run Code Online (Sandbox Code Playgroud)

(在发布查询后编辑已更正)

添加: 如果连接语法不适用于Oracle,那么如何:

UPDATE target_table 
SET special_id = st.source_special_id
FROM 
    target_table tt, source_table st
WHERE tt.another_id = st.another_id 
Run Code Online (Sandbox Code Playgroud)

关键是要连接两个表而不是使用当前使用的外部查询语法.


Ton*_*ews 6

source_table(another_id)上有索引吗?如果不是source_table将在target_table中的每一行完全扫描一次.如果target_table很大,这将需要一些时间.

对于某些target_table行,source_table中是否可能没有匹配?如果是这样,您的更新将为这些行将special_id设置为null.如果你想避免这样做:

UPDATE target_table tt
SET special_id = ( SELECT source_special_id
                   FROM source_table st
                   WHERE tt.another_id = st.another_id )
WHERE EXISTS( SELECT NULL
              FROM source_table st
              WHERE tt.another_id = st.another_id );
Run Code Online (Sandbox Code Playgroud)

如果 target_table.another_id被声明为引用source_table.another_id的外键(在这种情况下不太可能),这将起作用:

UPDATE
  ( SELECT tt.primary_key, tt.special_id, st.source_special_id
    FROM   tatget_table tt
    JOIN   source_table st ON st.another_id = tt.another_id
  )
SET special_id = source_special_id;
Run Code Online (Sandbox Code Playgroud)