【问题标题】:SQL : Oracle : Optimize LEFT Outer Join QuerySQL:Oracle:优化左外连接查询
【发布时间】:2019-03-08 06:15:45
【问题描述】:

我有 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;

【问题讨论】:

  • 左对齐 SQL 太难读了...

标签: sql oracle


【解决方案1】:

我在您的查询中看到的主要问题是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;

【讨论】:

  • 嗨蒂姆,感谢您的及时回复。我会测试一下,让你知道它是怎么回事。我是否正确假设将在我拥有完全权限的本地数据库上创建物化视图。远程 DBS 是我没有完全管理员权限的应用程序。
  • @venky_au 我猜你必须在你有权/有能力的地方创建视图。
  • 这非常适合我的要求。非常感谢您的专家建议。最后,他们的任何重复性管理/维护任务是否涉及我需要涵盖的物化视图。
  • 是的,如果两个表中的基础数据发生更改,您可能必须刷新并重新索引视图。但是,这对你来说是个问题吗?当我回答时,我有点想象这是一次性报告要求。
  • 嗨,蒂姆,不,这是一个持续的报告。没有刷新不应该是一个问题。你能否给我一些关于如何设置刷新的提示。如果刷新一天只发生一两次,我们应该没问题
【解决方案2】:

我会这样做:

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;

【讨论】:

  • 您好 Gaurav,感谢您的及时回复。我会对此进行测试,然后告诉你这是怎么回事。
【解决方案3】:

您的查询基本上是:

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

这将至少允许单独优化每个表 - 这应该会有所帮助。

显然,如果您具有设置跨服务器物化视图的权限和愿望,则使用物化视图的解决方案会更快。物化视图存在额外的维护问题,尤其是当您有多个此类视图并假设它们同时更新时。

【讨论】:

  • 嗨,戈登,感谢您的及时回复。我会对此进行测试,然后告诉你这是怎么回事。
  • 我试过了,效果很好。谢谢。但是只有一个问题,如果您看到我的原始查询,我正在使用 CASE 语句打印 AGSTAT。我如何使用 coalesce 做到这一点?
猜你喜欢
  • 1970-01-01
  • 2017-04-04
  • 1970-01-01
  • 2011-04-29
  • 1970-01-01
  • 2012-01-15
  • 2020-02-14
  • 2016-02-16
  • 1970-01-01
相关资源
最近更新 更多