SQL:Oracle:优化左侧外部联接查询
我有1个本地表(除了一个之外,所有列名都不同于远程表)和2个远程表(列名相同),我需要为它们组合数据 下面是我使用leftouterjoin和UNION编写的查询,但是性能很慢 任何人都可以帮助优化这个查询吗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
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,谢谢你的及时回复。我会测试一下,让你知道这是怎么回事。