Oracle 查询性能——多个复杂的窗口函数
Posted
技术标签:
【中文标题】Oracle 查询性能——多个复杂的窗口函数【英文标题】:Oracle Query Performance -- Multiple Complex Window Functions 【发布时间】:2019-10-15 19:18:29 【问题描述】:这个查询一直是我存在的祸根。它在一个大约有 6 亿行的表上。该表未分区或索引。
我有 24 个用于历史趋势的数据表。我不得不调整代码,现在需要重新运行。每个月需要运行 2-3 个小时。我最近刚刚尝试一次运行 24 个查询.. 而我的 DBA.. 不高兴(陷入整个数据库)
我尝试过分区和索引,但没有看到性能提升。我尝试了不同级别 CTE 的不同方法.. 或子选择.. 没有运气... 因为 UCID/CALLIDS 中的差距.. 这里有很多时间逻辑..
WITH
UCID
AS
(SELECT /*+ PARALLEL(8) */
--REGULAR FIELDS
SEGSTART + (DISPTIME / 86400) CALLSTART
,SEGSTART +
((DISPTIME + ANSHOLDTIME + talktime) / 86400) +
NvL(
(CASE
WHEN ORIGLOGIN IS NOT NULL AND
ANSLOGIN IS NULL
THEN
(CONSULTTIME + ORIGHOLDTIME) / 86400
END)
,0) CALLSTOP
-- +NvL((cASE WHEN ORIGLOGIN IS NOT NULL AND ANSLOGIN IS NULL THEN CONSULTTIME/86400 END),0)CALLSTOP
,SEGSTART
,SEGSTOP
,split1
,UCID
,DIALED_NUM
,CALLING_PTY
,TRANSFERRED
,CALL_DTL_REC_ID
,CMSHOST COMPLEX_CMSHOST
,CALLID COMPLEX_CALLID
,anslogin n_anslogin
,origlogin n_origlogin
--UCID WINDOW MATCHES
,LAST_VALUE(a.ASAIUUI)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART) ASAIUUI
,LAST_VALUE(a.ORIGLOGIN)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART) ORIGLOGIN
,LAST_VALUE(a.ANSLOGIN)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART) ANSLOGIN
,FIRST_VALUE(a.DIALED_NUM)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART
ORDER BY
CASE WHEN LENGTH(DIALED_NUM) > 8 THEN 1 ELSE 0 END ASC
,SEGSTOP DESC) DIALEDNUM
,LAST_VALUE(a.transferred)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART) TRANSFER
--MULTI ROW WINDOW MATCHES
,FIRST_VALUE(CALLID)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART
ORDER BY ((DISPTIME + ANSHOLDTIME + talktime + RINGTIME) / 86400) DESC) CALLID
,FIRST_VALUE(a.acd)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART
ORDER BY ((DISPTIME + ANSHOLDTIME + talktime + RINGTIME) / 86400) DESC) ACD
,first_VALUE(a.DISSPLIT)
IGNORE NULLS
OVER(
PARTITION BY ucid
,segstart
ORDER BY ((DISPTIME + ANSHOLDTIME + talktime + RINGTIME) / 86400) DESC) DISSPLIT
,FIRST_VALUE(a.cmshost)
IGNORE NULLS
OVER(
PARTITION BY UCID
,SEGSTART
ORDER BY ((DISPTIME + ANSHOLDTIME + talktime + RINGTIME) / 86400) DESC) CMSHOST
,FIRST_VALUE(anslogin)
OVER(
PARTITION BY ucid
ORDER BY segstart ASC NULLS FIRST) COMPLEX_ANSLOGIN
,FIRST_VALUE(anslogin)
IGNORE NULLS
OVER(
PARTITION BY ucid
ORDER BY segstart ASC) COMPLEX_ANSLOGIN_NONULLS
,FIRST_VALUE(CALL_DTL_REC_ID)
OVER(
PARTITION BY ucid
ORDER BY segstart ASC NULLS FIRST) COMPLEX_CALL_DTL_REC_ID
,ROW_NUMBER()
OVER(
PARTITION BY ucid
,CASE
WHEN anslogin IS NOT NULL THEN ucid
ELSE anslogin
END
ORDER BY segstart ASC) COMPLEX_RN_ANS
,first_VALUE(a.ASAIUUI)
IGNORE NULLS
OVER(
PARTITION BY UCID
ORDER BY CASE WHEN a.asaiuui IS NOT NULL THEN a.segstart END) COMPLEX_ASAIUUI
,ROW_NUMBER()
OVER(
PARTITION BY ucid
,CASE WHEN origlogin IS NOT NULL THEN origlogin END
ORDER BY segstart ASC) COMPLEX_RN_ORIG
,FIRST_VALUE(a.ORIGLOGIN)
OVER(
PARTITION BY UCID
,to_char(
segstop
,'DD/MM/YYYY HH24-MI-SS')) COMPLEX_ORIGLOGIN
,FIRST_VALUE(a.ORIGLOGIN)
IGNORE NULLS
OVER(
PARTITION BY ucid
,to_char(
segstop
,'DD/MM/YYYY HH24-MI-SS')
ORDER BY segstart ASC) COMPLEX_ORIGLOGIN_NONULLS
,FIRST_VALUE(anslogin)
IGNORE NULLS
OVER(
PARTITION BY ucid
,origlogin
ORDER BY segstart DESC) COMPLEX_ANSLOGIN_ORIG
,LAST_VALUE(a.transferred)
IGNORE NULLS
OVER(
PARTITION BY ucid
ORDER BY segstart ASC) COMPLEX_TRANSFER
--ASAIUUI WINDOW MATCHES
,LAST_VALUE(a.ASAIUUI)
IGNORE NULLS
OVER(
PARTITION BY CALLID
,acd
,CASE
WHEN substr(
ASAIUUI
,0
,3) = '000' AND
asaiuui IS NOT NULL
THEN
1
END
ORDER BY segstop) ASAIUUI_ASAIUUI
,LAST_VALUE(a.ORIGLOGIN)
IGNORE NULLS
OVER(
PARTITION BY CALLID
,SEGSTART
,acd) ASAIUUI_ORIGLOGIN
,LAST_VALUE(a.ANSLOGIN)
IGNORE NULLS
OVER(
PARTITION BY CALLID
,SEGSTART
,acd) ASAIUUI_ANSLOGIN
FROM
RDHONDT.TEMPAVAYA_PART a
WHERE
a.segstart BETWEEN '1-SEP-2019' AND '1-OCT-2019' --ucid = '00002108121561939226'
AND
A.dissplit NOT IN (-1) AND
a.acd IN (1
,2
,3))
SELECT
*
FROM
( --SELECT THE PRI MATCH TYPE ***** HIGH QUERY COST... REVISIT
SELECT /*+ PARALLEL(8) */
t2.*
,row_number()
OVER(
PARTITION BY REC_ucid
,rec_login
ORDER BY
CASE
WHEN MATCHTYPE = 'UCID' THEN 1
WHEN MATCHTYPE = 'UCID_MULTIPARTY' THEN 2
WHEN MATCHTYPE = 'ASAIUUI' THEN 3
WHEN MATCHTYPE = 'UCID_OUTBOUND' THEN 4
WHEN MATCHTYPE = 'ORPHAN_SEGMENT' THEN 5
WHEN matchtype = 'AM_SEGTIME' THEN 6
END ASC
,transfer DESC) rn
--UNION ALL THE MATCH TYPES
FROM
( --!!!MATCH TYPE ASAIUU
SELECT
O.ucid ORIG_UCID
,d.ucid REC_UCID
,O.callid ORIG_CALLID
,d.callid REC_CALLID
,O.callstart ORIG_START
,o.callstop ORIG_STOP
,D.callstart REC_START
,o.callstop REC_STOP
,o.segstart ORIG_SEGSTART
,o.segstop ORIG_SEGSTOP
,d.segstart REC_SEGSTART
,d.segstop REC_SEGSTOP
,O.ASAIUUI_anslogin ORIG_LOGIN
,D.ASAIUUI_anslogin REC_LOGIN
,O.dissplit ORIG_SPLIT
,O.acd ORIG_ACD
,D.DISSPLIT REC_SPLIT
,D.acd REC_ACD
,D.CMSHOST REC_HOST
,O.cmshost ORIG_HOST
,D.DIALEDNUM DIALED_NUM
,CASE
WHEN (D.callstop > O.callstop OR
D.callstop > O.segstop OR
d.segstop > o.segstop)
THEN
1
ELSE
0
END TRANSFER
,'ASAIUUI' MATCHTYPE
FROM
ucid O
INNER JOIN ucid D
ON (D.segstart >= O.CALLSTART AND
D.segstart <= O.CALLSTOP) AND
substr(
d.ASAIUUI_ASAIUUI
,-7
,7) = o.ASAIUUI_anslogin
WHERE
O.ASAIUUI_ANSLOGIN IS NOT NULL AND
O.ASAIUUI_anslogin <> d.ASAIUUI_anslogin
--!!!MATCH TYPE MULTIROW
UNION ALL
SELECT
m.UCID
,m.REC_UCID
,m.ORIG_CALLID
,m.REC_CALLID
,m.ORIG_START
,m.ORIG_STOP
,m.REC_START
,m.REC_STOP
,m.orig_segstart
,m.orig_segstop
,m.rec_segstart
,m.rec_segstop
,m.ORIG_LOGIN
,m.REC_LOGIN
,m.ORIG_SPLIT
,m.ORIG_ACD
,m.REC_SPLIT
,m.REC_ACD
,m.REC_HOST
,m.ORIG_HOST
,m.DIALED_NUM
,CASE
WHEN (m.REC_STOP > m.ORIG_STOP OR
m.REC_STOP > m.ORIG_SEGSTOP OR
m.REC_SEGSTOP > m.ORIG_SEGSTOP) OR
(M.ORIG_SEGSTART = M.REC_SEGSTART AND
M.ORIG_SEGSTOP = M.REC_SEGSTOP)
THEN
1
ELSE
0
END TRANSFER
,m.MATCHTYPE
FROM
(SELECT /*+ PARALLEL(8) */
t1.ucid
,max(ucid) KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) rec_ucid
,max(complex_callid)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) orig_callid
,max(complex_callid)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) rec_callid
,max(callstart)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_start
,max(callstop)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_STOP
,max(segstart)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_SEGSTART
,max(segstop)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_SEGSTOP
,max(callstart)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_START
,max(callstop)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_stop
,max(segstart)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_segSTART
,max(segstop)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_segstop
,max(
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1
THEN
origlogin
WHEN orig_row = 1
THEN
CASE
WHEN ANSLOGIN IS NOT NULL THEN anslogin
WHEN origlogin IS NOT NULL THEN origlogin
END
END)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1
THEN
1
WHEN orig_row = 1
THEN
CASE
WHEN ANSLOGIN IS NOT NULL THEN 2
WHEN origlogin IS NOT NULL THEN 3
END
END) ORIG_LOGIN
,max(anslogin)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_login
,max(dissplit)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_SPLIT
,max(acd)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_ACD
,max(dissplit)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_split
,max(acd) KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_acd
,max(cmshost)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN ans_row = 1 THEN 1 END) REC_host
,max(cmshost)
KEEP (DENSE_RANK FIRST
ORDER BY
CASE
WHEN ORIG_ROW_MULTITRANSFER = 1 THEN 1
WHEN orig_row = 1 THEN 2
END) ORIG_HOST
,max(dialed_num)
KEEP (DENSE_RANK FIRST ORDER BY CASE WHEN dial_row = 1 THEN DIALED_NUM END) DIALED_NUM
,'UCID_MULTIPARTY' MATCHTYPE
FROM
(SELECT /*+ PARALLEL(8) */
d.ucid
,d.SEGSTART
,d.SEGSTOP
,d.DISSPLIT
,d.TRANSFERRED
,d.ACD
,D.CMSHOST
,d.n_ORIGLOGIN origlogin
,d.n_ANSLOGIN anslogin
,d.DIALED_NUM
,d.CALLING_PTY
,d.ASAIUUI
,d.callstart
,d.callstop
,d.call_dtl_rec_id test
,d.COMPLEX_ASAIUUI
--if anslogin is blank on first call then select the first call rec in the ucid
,CASE
WHEN (COMPLEX_ANSLOGIN IS NULL AND
COMPLEX_CALL_DTL_REC_ID = d.call_dtl_rec_id) OR
n_origlogin = substr(
COMPLEX_ASAIUUI
,-7
,7)
THEN
1
ELSE
CASE
WHEN COMPLEX_ANSLOGIN IS NOT NULL AND
n_anslogin IS NOT NULL
THEN
COMPLEX_RN_ANS
END
END ORIG_ROW
,CASE
WHEN n_origlogin = substr(
COMPLEX_ASAIUUI
,-7
,7)
THEN
COMPLEX_RN_ORIG
END ORIG_ROW_MULTITRANSFER
--first anslogin is blank and row is the first non blank anslogin
,CASE
WHEN COMPLEX_ANSLOGIN IS NULL AND
n_anslogin = COMPLEX_ANSLOGIN_NONULLS
THEN
1
ELSE
--no origin login
CASE
WHEN n_origlogin IS NULL
THEN
--
CASE
WHEN n_anslogin IS NOT NULL AND
COMPLEX_ANSLOGIN = COMPLEX_ORIGLOGIN
THEN
1
ELSE
CASE
WHEN n_anslogin IS NOT NULL AND
COMPLEX_ANSLOGIN_nONULLS = n_anslogin AND
substr(
COMPLEX_ASAIUUI
,-7
,7) = COMPLEX_ORIGLOGIN
THEN
1
ELSE
CASE
WHEN n_anslogin IS NOT NULL AND
(COMPLEX_ANSLOGIN = d.n_origlogin OR
COMPLEX_ANSLOGIN = COMPLEX_ORIGLOGIN_NONULLS) AND
COMPLEX_ANSLOGIN_ORIG = d.n_ANSLOGIN
THEN
1
END
END
END
ELSE
--ORIGLOGIN IS EQUAL TO FIRST ANSLOGIN (DIALED OUT) AND ITS THE FIRST
CASE
WHEN n_anslogin IS NOT NULL AND
COMPLEX_ANSLOGIN = d.n_origlogin AND
COMPLEX_ANSLOGIN = COMPLEX_ORIGLOGIN_NONULLS AND
COMPLEX_ANSLOGIN_ORIG = d.n_ANSLOGIN
THEN
1
END
END
END ANS_ROW
,CASE
WHEN COMPLEX_ANSLOGIN IS NULL AND
d.CALL_DTL_REC_ID = COMPLEX_CALL_DTL_REC_ID
THEN
1
ELSE
--DIALED OUT AND BY THE SAME LOGIN AS THE ANSROW LOGIN
CASE
WHEN n_origlogin = substr(
COMPLEX_ASAIUUI
,-7
,7)
THEN
1
ELSE
CASE
WHEN n_origlogin IS NOT NULL AND
COMPLEX_ANSLOGIN = d.n_origlogin
THEN
COMPLEX_RN_ORIG
END
END
END DIAL_ROW
,CASE WHEN COMPLEX_ANSLOGIN IS NULL THEN 1 ELSE COMPLEX_TRANSFER END transfer
,COMPLEX_CALLID
FROM
ucid d) t1
GROUP BY
ucid) m
--!!!MATCH TYPE UCID
UNION ALL
SELECT /*+ PARALLEL(6) */
O.ucid ORIG_UCID
,d.ucid REC_UCID
,O.callid ORIG_CALLID
,d.callid REC_CALLID
,O.callstart ORIG_START
,o.callstop ORIG_STOP
,D.callstart REC_START
,D.callstop REC_STOP
,o.segstart ORIG_SEGSTART
,o.segstop ORIG_SEGSTOP
,d.segstart REC_SEGSTART
,d.segstop REC_SEGSTOP
,O.anslogin ORIG_LOGIN
,D.anslogin REC_LOGIN
,O.dissplit ORIG_SPLIT
,O.acd ORIG_ACD
,D.DISSPLIT REC_SPLIT
,D.acd REC_ACD
,D.CMSHOST REC_HOST
,O.cmshost ORIG_HOST
,D.DIALEDNUM DIALED_NUM
,CASE
WHEN (D.callstop > O.callstop OR
D.callstop > O.segstop OR
d.segstop > o.segstop)
THEN
1
ELSE
0
END TRANSFER
,'UCID' MATCHTYPE
FROM
ucid D
INNER JOIN ucid O
ON (D.SEGSTART >= O.CALLSTART AND
D.SEGSTART <= O.CALLSTOP + 0.00034722222) AND
O.anslogin = D.origlogin
WHERE
O.ANSLOGIN IS NOT NULL AND
D.ORIGLOGIN IS NOT NULL AND
O.anslogin <> d.anslogin AND
o.anslogin IS NOT NULL
--!!!MATCH TYPE LOGIN_UNMATCHED
UNION ALL
SELECT /*+ PARALLEL(6) */
O.ucid ORIG_UCID
,d.ucid REC_UCID
,O.callid ORIG_CALLID
,d.callid REC_CALLID
,O.callstart ORIG_START
,o.callstop ORIG_STOP
,D.callstart REC_START
,D.callstop REC_STOP
,o.segstart ORIG_SEGSTART
,o.segstop ORIG_SEGSTOP
,d.segstart REC_SEGSTART
,d.segstop REC_SEGSTOP
,O.ORIGlogin ORIG_LOGIN
,D.anslogin REC_LOGIN
,O.dissplit ORIG_SPLIT
,O.acd ORIG_ACD
,D.DISSPLIT REC_SPLIT
,D.acd REC_ACD
,D.CMSHOST REC_HOST
,O.cmshost ORIG_HOST
,D.DIALEDNUM DIALED_NUM
,CASE
WHEN (D.callstop > O.callstop OR
D.callstop > O.segstop OR
d.segstop > o.segstop)
THEN
1
ELSE
0
END TRANSFER
,'UCID_OUTBOUND' MATCHTYPE
FROM
ucid D
INNER JOIN ucid O
ON (D.SEGSTART >= O.CALLSTART AND
D.SEGSTART <= O.CALLSTOP) AND
O.ORIGLOGIN = D.origlogin
WHERE
O.ANSLOGIN IS NULL AND
D.ORIGLOGIN IS NOT NULL AND
O.ORIGLOGIN IS NOT NULL AND
LENGTH(d.DIALED_NUM) <= 7
UNION ALL
SELECT /*+ PARALLEL(6) */
NULL ORIG_UCID
,d.ucid REC_UCID
,NULL ORIG_CALLID
,d.callid REC_CALLID
,NULL ORIG_START
,NULL ORIG_STOP
,D.callstart REC_START
,D.callstop REC_STOP
,NULL ORIG_SEGSTART
,NULL ORIG_SEGSTOP
,d.segstart REC_SEGSTART
,d.segstop REC_SEGSTOP
,d.origlogin ORIG_LOGIN
,d.anslogin REC_LOGIN
,-1 ORIG_SPLIT
,-1 ORIG_ACD
,D.DISSPLIT REC_SPLIT
,D.acd REC_ACD
,D.CMSHOST REC_HOST
,'' ORIG_HOST
,D.DIALEDNUM DIALED_NUM
,0 TRANSFER
,'ORPHAN_SEGMENT' MATCHTYPE
FROM
ucid D
WHERE
D.ORIGLOGIN IS NOT NULL AND
D.ANSLOGIN IS NOT NULL
UNION ALL
---test
SELECT /*+ PARALLEL(6) */
O.ucid ORIG_UCID
,d.ucid REC_UCID
,O.callid ORIG_CALLID
,d.callid REC_CALLID
,O.callstart ORIG_START
,o.callstop ORIG_STOP
,D.callstart REC_START
,d.callstop REC_STOP
,o.segstart ORIG_SEGSTART
,o.segstop ORIG_SEGSTOP
,d.segstart REC_SEGSTART
,d.segstop REC_SEGSTOP
,O.origlogin ORIG_LOGIN
,D.ANSLOGIN REC_LOGIN
,O.dissplit ORIG_SPLIT
,O.acd ORIG_ACD
,D.DISSPLIT REC_SPLIT
,D.acd REC_ACD
,D.CMSHOST REC_HOST
,O.cmshost ORIG_HOST
,O.DIALED_NUM DIALED_NUM
,CASE
WHEN (D.callstop > O.callstop OR
D.callstop > O.segstop OR
d.segstop > o.segstop)
THEN
1
ELSE
0
END TRANSFER
,'AM_SEGTIME' MATCHTYPE
FROM
ucid d
INNER JOIN ucid o
ON --call started no more than 60 seconds after origin
o.segstart BETWEEN d.SEGSTART - INTERVAL '60' SECOND AND d.SEGSTART AND
d.segstop BETWEEN o.segstop AND o.segstop + INTERVAL '60' SECOND AND
--(o.segstop = d.callstop
((o.segstop = d.callstop OR
o.segstop = d.segstop) OR
(o.callstart BETWEEN d.SEGSTART - INTERVAL '5' SECOND AND d.SEGSTART AND
d.segstop BETWEEN o.segstop AND o.segstop + INTERVAL '60' SECOND))
WHERE
d.dissplit IN (2619
,2618
,2614
,428
,137
,2617
,125
,136
,3067
,127
,2616
,36) AND
length(o.dialed_num) <= 8 -- the origin call is a dial out
AND
o.origlogin IS NOT NULL AND
o.anslogin IS NULL --the destination call is answered with an unknown origin
AND
d.anslogin IS NOT NULL AND
d.origlogin IS NULL AND
o.split1 = -1 AND
d.split1 <> -1) t2
WHERE
rec_login <> orig_login) t3
WHERE
rn = 1
计划:
【问题讨论】:
圣洁缺乏缩进蝙蝠侠 我知道这太可怕了 ***.com/help/minimal-reproducible-example "在创建最小示例时,不要为了简洁而牺牲清晰度。使用一致的命名和缩进,并在需要时包含代码 cmets。使用代码编辑器的快捷方式来格式化代码。另外,使用空格而不是选项卡 - 选项卡在 Stack Overflow 上的格式可能不正确。" 本着上述 cmets 的精神,没有人能够帮助您调整那么大而丑陋的东西,而无需至少获得解释计划。我的建议是分而治之。将其分解为更小的查询,并找出对性能影响最大的地方。调整它。继续下一个性能最差的子查询或函数,依此类推。起泡、冲洗、重复。 【参考方案1】:您在每个选择上都有随机并行提示,这并不总是有助于提高性能,然后是一大堆查询,我宁愿在类似过程的代码中调用它们,然后将它们插入到一些临时表中。
插入表格... 与...选择...; 犯罪; 插入表... 选择 ... ; 犯罪; 等等。
对于内联函数,我会根据某些条件取最小值和最大值。
【讨论】:
以上是关于Oracle 查询性能——多个复杂的窗口函数的主要内容,如果未能解决你的问题,请参考以下文章