SQL:Oracle:优化左外部联接查询

时间:2018-10-03 04:49:04

标签: sql oracle

我有1个本地表(所有列名与远程表都不同,除了一个)和2个远程表(它们具有相同的列名),我需要为它们合并数据。

以下是我使用LEFT OUTER JOIN和UNION编写的查询,但是性能很慢。

任何人都可以帮助优化此查询吗?

select
"CONTROL_M_SERVER",
"HOST",
CASE
WHEN "AGSTAT" = 'V' THEN 'Available'
WHEN "AGSTAT" = 'U' THEN 'Unavailable'
WHEN "AGSTAT" = 'R' THEN 'Discovering'
ELSE 'Not Defined in Control-M'
END as Agent_Status,
T1.VERSION,
"PORTS",
"MANAGEMENT_IP",
"OPERATING_SYSTEM",
"CLUSTER_ALIAS",
"NODEGROUP",
"APPLICATION_ID",
"DATE_CONFIGURED",
"CONFIGURED_BY"
from "CTMAGENTAUDIT" T1
left outer join (select NODEID,AGSTAT from CMR_NODES@SPDB UNION ALL select NODEID,AGSTAT from CMR_NODES@DEVDB) T2 on T2.NODEID = T1.HOST;

3 个答案:

答案 0 :(得分:3)

我在查询中看到的主要问题是CTMAGENTAUDIT与包含联合的子查询之间最外面的左联接。该子查询的问题在于,按照书面规定,Oracle可能无法对联接使用任何索引。这意味着Oracle在加入时可能不得不求助于较慢的方法,可能会进行全面扫描。

这里的一种方法是创建一个包含联合查询的实例化视图,然后对其进行索引:

CREATE MATERIALIZED VIEW T2 AS
SELECT NODEID, AGSTAT FROM CMR_NODES@SPDB
UNION ALL
SELECT NODEID, AGSTAT FROM CMR_NODES@DEVDB;

CREATE INDEX mv_node_idx ON T2 (NODEID);

有了该索引的物化视图,我希望您的查询现在执行得更好:

SELECT
    CONTROL_M_SERVER,
    HOST,
    CASE WHEN AGSTAT = 'V' THEN 'Available'
         WHEN AGSTAT = 'U' THEN 'Unavailable'
         WHEN AGSTAT = 'R' THEN 'Discovering'
         ELSE 'Not Defined in Control-M' END AS Agent_Status,
    T1.VERSION,
    PORTS,
    MANAGEMENT_IP,
    OPERATING_SYSTEM,
    CLUSTER_ALIAS,
    NODEGROUP,
    APPLICATION_ID,
    DATE_CONFIGURED,
    CONFIGURED_BY
FROM CTMAGENTAUDIT T1
LEFT OUTER JOIN T2
    ON T2.NODEID = T1.HOST;

答案 1 :(得分:0)

我会做这样的事情:

select
"CONTROL_M_SERVER",
"HOST",
CASE
WHEN "AGSTAT" = 'V' THEN 'Available'
WHEN "AGSTAT" = 'U' THEN 'Unavailable'
WHEN "AGSTAT" = 'R' THEN 'Discovering'
ELSE 'Not Defined in Control-M'
END as Agent_Status,
T1.VERSION,
"PORTS",
"MANAGEMENT_IP",
"OPERATING_SYSTEM",
"CLUSTER_ALIAS",
"NODEGROUP",
"APPLICATION_ID",
"DATE_CONFIGURED",
"CONFIGURED_BY",
(select t2.NODEID, t2.AGSTAT from CMR_NODES@SPDB t2 where t1.host = t2.nodeid),  
(select t3.NODEID, t3.AGSTAT from CMR_NODES@DEVDB t3 where T1.HOST = T3.NODEID) from t1;

答案 2 :(得分:0)

您的查询基本上是:

select . . .
from CTMAGENTAUDIT T1 left outer join
     (select NODEID, AGSTAT
      from CMR_NODES@SPDB UNION ALL
      select NODEID, AGSTAT
      from CMR_NODES@DEVDB
     ) T2
     on T2.NODEID = T1.HOST;

假设NODEID / AGSTAT组合在每个CMR_NODE表中都是唯一的,我将其写为:

select . . .,
       coalesce(s1.AGSTAT, s2.AGSTAT) as AGSTAT,
       (case coalesce(s1.AGSTAT, s2.AGSTAT) 
            when 'V' then 'Available'
            when 'U' then 'Unavailable'
            when 'R' then 'Discovering'
            else 'Not Defined in Control-M'
        end) as Agent_Status
from CTMAGENTAUDIT T1 left outer join
     CMR_NODES@SPDB s1
     on s1.NODEID = T1.HOST left outer join
     CMR_NODES@DEVDB s2
     on s1.NODEID = T1.HOST

这至少将允许分别优化每个表-这应该有所帮助。

很明显,如果您具有设置跨服务器实例化视图的权限并希望实现,则包含实例化视图的解决方案将更快。物化视图还有其他维护问题,特别是如果您有多个这样的视图并假定它们是在同一时间更新的。