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

SQL:Oracle:优化左侧外部联接查询,sql,oracle,Sql,Oracle,我有1个本地表(除了一个之外,所有列名都不同于远程表)和2个远程表(列名相同),我需要为它们组合数据 下面是我使用leftouterjoin和UNION编写的查询,但是性能很慢 任何人都可以帮助优化这个查询吗 select "CONTROL_M_SERVER", "HOST", CASE WHEN "AGSTAT" = 'V' THEN 'Available' WHEN "AGSTAT" = 'U' THEN 'Unavailable' WHEN "AGSTAT" = 'R' THEN 'Dis

我有1个本地表(除了一个之外,所有列名都不同于远程表)和2个远程表(列名相同),我需要为它们组合数据

下面是我使用leftouterjoin和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;

我在您的查询中看到的主要问题是
CTMAGENTAUDIT
和包含联合的子查询之间最外层的左连接。这个子查询的问题是,正如前面所写的,Oracle不可能为连接使用任何索引。这意味着Oracle在加入时可能不得不采用较慢的方法,可能是完全扫描

这里的一种方法是创建包含union查询的物化视图,然后为其编制索引:

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;

我会这样做:

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;

您的查询基本上是:

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\u节点
表中是唯一的,我将这样写:

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
这将至少允许单独优化每个表——这应该会有所帮助


显然,如果您有权限并希望设置跨服务器的物化视图,那么使用物化视图的解决方案会更快。物化视图还存在其他维护问题,特别是如果您有多个这样的视图,并且假设它们同时更新。

左对齐SQL非常难阅读…嗨,Tim,感谢您的及时响应。我会测试一下,让你知道它是怎么回事。我假设物化视图是在我拥有完全权限的本地数据库上创建的,对吗。远程DBS是我没有完全管理权限的应用程序。@venky_au我想你必须在你有权限/能力的地方创建视图。这非常适合我的要求。非常感谢您的专家建议。最后,他们的任何重复性管理/维护任务是否涉及到具体化视图,我需要对其进行分析。是的,如果两个表中的基础数据发生更改,您可能必须刷新视图并重新编制其索引。但是,这对你来说会是个问题吗?当我回答时,我有点想象这是一个一次性的报告要求。嗨,蒂姆,不,这是一个持续的报告。而且不需要提神也不成问题。你能给我一些关于如何设置刷新的提示吗。如果一天只刷新一到两次,我们会很好的。嗨,戈登,谢谢你的及时回复。我会测试一下,让你知道这是怎么回事。我试过了,效果很好。谢谢不过只有一个问题,如果您看到我的原始查询,我将使用CASE语句打印AGSTAT。我该如何使用coalesce?嗨,Gaurav,谢谢你的及时回复。我会测试一下,让你知道这是怎么回事。