我怎样才能优化视图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 行。
您不必这样做。
解决此问题的一种方法是将所有相关的DATECHARGEMENT
和DATENSF
值预先聚合一次,然后将结果集加入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中创建表,如何写sql语句才能保证表不重复创建,也就是说,如何让他不提示表或视图已存在