我怎样才能优化视图oracle sql

Posted

技术标签:

【中文标题】我怎样才能优化视图oracle sql【英文标题】:how can i optimize view oracle sql 【发布时间】:2019-11-20 17:21:28 【问题描述】:

我不擅长 sql 和 oracle,我需要帮助来优化这个视图,以便尽快得到结果。目前,我运行它的 select 子句需要 7 分钟。

这是视图:

CREATE OR REPLACE FORCE VIEW "DMUSEWADM"."SOUS_FAMILLE_WITH_CATALOG_INFO" 

("IDSOUSFAMILLE", "LIBELLESOUSFAMILLE", "DATEMODIFSF", "IDFAMILLE", 
"CHEMIN", "GNP", "TYPEFICHIER", "ESTPLANIFIABLE", "DATEPLANIFIABLE", 
"AUTEURMODIFSF", "NATURESOUSFAMILLE", "LIBELLEMETIERSOUSFAMILLE", 
"CONTACTPRODUCTEUR", "CATALOGVISIBILITY", "PREVISIONALDATE", 
"DATEDERNIERCHARGEMENT", "DATEPROCHAINCHARGEMENT", "LIBELLEFAMILLE") AS 

SELECT SF."IDSOUSFAMILLE",SF."LIBELLESOUSFAMILLE",SF."DATEMODIFSF",SF."IDFAMILLE",SF."CHEMIN",SF."GNP", SF."TYPEFICHIER",SF."ESTPLANIFIABLE",SF."DATEPLANIFIABLE",SF."AUTEURMODIFSF",SF."NATURESOUSFAMILLE",SF."LIBELLEMETIERSOUSFAMILLE",SF."CONTACTPRODUCTEUR",SF."CATALOGVISIBILITY",SF."PREVISIONALDATE", 
( SELECT datefinchrgt from chargement where numchrgt = ( select  max(numchrgt) from CHARGEMENT where nomhbase = ( select nomhbase from hbase where nomes = SF.IDSOUSFAMILLE ) and etatchrgt = 'OK')
) as DATEDERNIERCHARGEMENT, 
( SELECT (
    CASE WHEN DATECHARGEMENT IS NOT NULL THEN
        (
        CASE WHEN DATENSF IS NOT NULL THEN
            GREATEST(DATECHARGEMENT, DATENSF)
        ELSE
            DATECHARGEMENT
        END
        )
    ELSE
        DATENSF
    END
    )
  FROM 
    (
      SELECT 
        subsf.idsousfamille as subid,
        (SELECT max(c.dateauplustot) FROM CHARGEMENT c, HBASE h WHERE c.typechrgt = 'HBASEESDATA' and c.etatchrgt = 'PREVU' and c.nomhbase = h.nomhbase and h.nomes = subsf.idsousfamille) as DATECHARGEMENT,
        (SELECT max(nsf.dateauplustot) FROM NAS_SOUSFAMILLE nsf WHERE nsf.etatchrgt = 'PREVU' AND nsf.sousfamille = subsf.idsousfamille) as DATENSF
      FROM sousfamille subsf
    ) 
 WHERE subid = SF.idsousfamille
) as DATEPROCHAINCHARGEMENT,

( 
  SELECT f.libelleFamille from famille f where sf.idfamille = f.idfamille
) as LIBELLEFAMILLE

FROM SOUSFAMILLE SF;

我该如何优化它以减少执行时间?

我会很感激任何帮助:)

这里是查询的解释计划

【问题讨论】:

您是否执行了解释计划以查看查询访问权限?这是要做的第一件事并发布。 调整 Oracle 查询不仅仅是查看 SQL 语句并抚摸下巴。我们需要的信息比您迄今为止提供的信息要多得多。请阅读this other read,了解询问 Oracle 性能问题的正确方法。 @OldProgrammer 怎么办? docs.oracle.com/cd/B19306_01/server.102/b14211/… @OldProgrammer 这里是添加到问题描述中的解释计划 【参考方案1】:

正如其他 cmets 已经提到的,您的第一步是获取查询执行计划,并在那里寻找瓶颈。

但是,我立即在这里看到了多个危险信号。这是其中之一。

您正在为sousfamille 的每一行运行相关的聚合子查询。

  SELECT 
    subsf.idsousfamille as subid,
    (SELECT max(c.dateauplustot) FROM CHARGEMENT c, HBASE h WHERE c.typechrgt = 'HBASEESDATA' and c.etatchrgt = 'PREVU' and c.nomhbase = h.nomhbase and h.nomes = subsf.idsousfamille) as DATECHARGEMENT,
    (SELECT max(nsf.dateauplustot) FROM NAS_SOUSFAMILLE nsf WHERE nsf.etatchrgt = 'PREVU' AND nsf.sousfamille = subsf.idsousfamille) as DATENSF
  FROM sousfamille subsf

假设您的 sousfamille 表有 1M 行,NAS_SOUSFAMILLE 有 1M 行,那么您总共将读取 1G 行。

您不必这样做。

解决此问题的一种方法是将所有相关的DATECHARGEMENTDATENSF 值预先聚合一次,然后将结果集加入sousfamille

SELECT 
    subsf.idsousfamille as subid,
    h.DATECHARGEMENT,
    nsf.DATENSF
  FROM sousfamille subsf
  left join (SELECT h.homes, max(c.dateauplustot) DATECHARGEMENT FROM CHARGEMENT c, HBASE h WHERE c.typechrgt = 'HBASEESDATA' and c.etatchrgt = 'PREVU' and c.nomhbase = h.nomhbase) h 
  on subsf.idsousfamille = h.homes
  left join (SELECT nsf.sousfamille, max(nsf.dateauplustot) DATENSF FROM NAS_SOUSFAMILLE nsf WHERE nsf.etatchrgt = 'PREVU') nsf
  on nsf.sousfamille = subsf.idsousfamille

试试看。

【讨论】:

感谢您的评论我在问题描述中添加了查询执行计划【参考方案2】:

你可以试试这个,但这是一个很长的查询我不知道我是否在某个地方犯了错误

查询:

SELECT SF."IDSOUSFAMILLE",
       SF."LIBELLESOUSFAMILLE",
       SF."DATEMODIFSF",
       SF."IDFAMILLE",
       SF."CHEMIN",
       SF."GNP",
       SF."TYPEFICHIER",
       SF."ESTPLANIFIABLE",
       SF."DATEPLANIFIABLE",
       SF."AUTEURMODIFSF",
       SF."NATURESOUSFAMILLE",
       SF."LIBELLEMETIERSOUSFAMILLE",
       SF."CONTACTPRODUCTEUR",
       SF."CATALOGVISIBILITY",
       SF."PREVISIONALDATE",

       d.datefinchrgt AS DATEDERNIERCHARGEMENT,

       CASE WHEN DATECHARGEMENT IS NOT NULL THEN (CASE WHEN DATENSF IS NOT NULL THEN GREATEST(DATECHARGEMENT, DATENSF)
                                                   ELSE DATECHARGEMENT END)
            ELSE DATENSF END AS DATEPROCHAINCHARGEMENT,

       f.libelleFamille AS LIBELLEFAMILLE         
FROM SOUSFAMILLE SF
LEFT JOIN famille f
    ON sf.idfamille = f.idfamille
LEFT JOIN sousfamille subsf
    ON subsf.idsousfamille = SF.idsousfamille
      LEFT JOIN (SELECT nsf.sousfamille,
                        max(nsf.dateauplustot) DATECHARGEMENT
                 FROM NAS_SOUSFAMILLE nsf
                 WHERE nsf.etatchrgt = 'PREVU'
                 GROUP BY nsf.sousfamille) nsf
              ON nsf.sousfamille = subsf.idsousfamille
      LEFT JOIN (SELECT h.nomes,
                        max(c.dateauplustot) DATENSF
                 FROM CHARGEMENT c
                 JOIN HBASE h
                   ON c.nomhbase = h.nomhbase
                   AND c.typechrgt = 'HBASEESDATA'
                   AND c.etatchrgt = 'PREVU'
                  GROUP BY  h.nomes) h
               ON h.nomes = subsf.idsousfamille
LEFT JOIN (SELECT c.datefinchrgt,
                  c.nomes
           FROM (SELECT ch.datefinchrgt,
                        hb.nomes,
                        ROW_NUMBER()OVER(PARTITION BY datefinchrgt ORDER BY ch.numchrgt desc) as rn
                 FROM hbase hb
                 JOIN CHARGEMENT ch
                   ON ch.nomhbase = hb.nomhbase
                   AND hb.etatchrgt = 'OK') c
            WHERE c.rn = 1) d
                ON d.nomes = SF.IDSOUSFAMILLE;

【讨论】:

以上是关于我怎样才能优化视图oracle sql的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE关联三表视图查询过慢问题,如何解决?

在oracle中创建表,如何写sql语句才能保证表不重复创建,也就是说,如何让他不提示表或视图已存在

Oracle查询转换之连接谓词推入

Oracle SQL 创建视图无效标识符

运行时解析 PL/SQL 的 Oracle Apex Cards 视图

oracle怎样跟踪一条sql语句的执行过程?