下面的原始查询执行需要 6 秒。但是,当我从双重联合语句中删除大部分 select union(仅保留 1)时,查询只需要 1.2 秒即可执行。有人可以告诉我问题是什么以及如何解决这个问题吗?
SELECT DISTINCT b.RNUM as ROW_NUM,
b.MAX_ROWNUM,
b.ta_or_od_id,
b.lnk_od_id,
b.bussiness_unit,
b.CIF,
b.pf_id,
b.grp_tsk_status,
b.grp_tsk_type_and_status,
ta.src_sys,
ta.DUE_DATE_VALUE,
ta.mod_at,
tr.ORDER_ID
FROM (SELECT 1 AS RNUM,
'ABC345IABX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00019' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 2 AS RNUM,
'ABC345IACX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00020' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla1|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 3 AS RNUM,
'ABC345IADX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00021' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla2|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 4 AS RNUM,
'ABC345IAEX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00022' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla3|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 5 AS RNUM,
'ABC345IAFX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00023' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla4|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 6 AS RNUM,
'ABC345IAGX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00024' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla5|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 7 AS RNUM,
'ABC345IAHX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00025' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla6|Open' AS grp_tsk_type_and_status
FROM DUAL) b
JOIN tsk_ref tr on case
when b.lnk_od_id is not null and regexp_like(b.lnk_od_id,
'^' || tr.od_id ||
'_|_' || tr.od_id || '$')
then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
LEFT OUTER JOIN rt_saving_cf rsc
ON rsc.rul_id = tr.rul_id AND (rsc.chn = tr.chn OR rsc.chn = 'ALL') AND
rsc.ex_only = ta.so AND rsc.act = 'Y'
WHERE tr.tsk_id IN (SELECT DISTINCT sl_id
FROM (SELECT tr.tsk_id, tr.pr_tsk_id
FROM (SELECT 1 AS RNUM,
'ABC345IABX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00019' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 2 AS RNUM,
'ABC345IACX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00020' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla1|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 3 AS RNUM,
'ABC345IADX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00021' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla2|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 4 AS RNUM,
'ABC345IAEX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00022' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla3|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 5 AS RNUM,
'ABC345IAFX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00023' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla4|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 6 AS RNUM,
'ABC345IAGX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00024' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla5|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 7 AS RNUM,
'ABC345IAHX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00025' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla6|Open' AS grp_tsk_type_and_status
FROM DUAL) b join tsk_ref tr on case when b.lnk_od_id is not null and
regexp_like(b.lnk_od_id,
'^' || tr.od_id || '_|_' ||
tr.od_id || '$') then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id
then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
WHERE TA.tsk_status IN ('Open', 'Rejected')
AND UPPER(TR.pr_id) IN ('MA179234')) UNPIVOT (sl_id FOR COL IN (tsk_id, pr_id)))
ORDER BY b.RNUM, b.ta_or_od_id, ta.DUE_DATE_VALUE ASC NULLS LAST, ta.mod_at DESC;
SELECT DISTINCT b.RNUM as ROW_NUM,
b.MAX_ROWNUM,
b.ta_or_od_id,
b.lnk_od_id,
b.bussiness_unit,
b.CIF,
b.pf_id,
b.grp_tsk_status,
b.grp_tsk_type_and_status,
ta.src_sys,
ta.DUE_DATE_VALUE,
ta.mod_at,
tr.ORDER_ID
FROM (SELECT 1 AS RNUM,
'ABC345IABX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00019' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 2 AS RNUM,
'ABC345IACX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00020' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla1|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 3 AS RNUM,
'ABC345IADX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00021' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla2|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 4 AS RNUM,
'ABC345IAEX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00022' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla3|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 5 AS RNUM,
'ABC345IAFX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00023' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla4|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 6 AS RNUM,
'ABC345IAGX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00024' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla5|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION
SELECT 7 AS RNUM,
'ABC345IAHX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00025' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla6|Open' AS grp_tsk_type_and_status
FROM DUAL) b
JOIN tsk_ref tr on case
when b.lnk_od_id is not null and regexp_like(b.lnk_od_id,
'^' || tr.od_id ||
'_|_' || tr.od_id || '$')
then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
LEFT OUTER JOIN rt_saving_cf rsc
ON rsc.rul_id = tr.rul_id AND (rsc.chn = tr.chn OR rsc.chn = 'ALL') AND
rsc.ex_only = ta.so AND rsc.act = 'Y'
WHERE tr.tsk_id IN (SELECT DISTINCT sl_id
FROM (SELECT tr.tsk_id, tr.pr_tsk_id
FROM (SELECT 1 AS RNUM,
'ABC345IABX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00019' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla|Open' AS grp_tsk_type_and_status
FROM DUAL) b join tsk_ref tr on case when b.lnk_od_id is not null and
regexp_like(b.lnk_od_id,
'^' || tr.od_id || '_|_' ||
tr.od_id || '$') then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id
then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
WHERE TA.tsk_status IN ('Open', 'Rejected')
AND UPPER(TR.pr_id) IN ('MA179234')) UNPIVOT (sl_id FOR COL IN (tsk_id, pr_id)))
ORDER BY b.RNUM, b.ta_or_od_id, ta.DUE_DATE_VALUE ASC NULLS LAST, ta.mod_at DESC;
我想加快查询速度。
开始调优之前,请使用公用表表达式 (CTE) 简化查询。另外,只要您知道行是唯一的,请将
UNION
替换为 UNION ALL
,以避免排序。下面的代码仅将新行放入 CTE 中,但您的真实版本还应包含 CTE 中的重复联接。
WITH NEW_ROWS AS
(
SELECT 1 AS RNUM,
'ABC345IABX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00019' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 2 AS RNUM,
'ABC345IACX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00020' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla1|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 3 AS RNUM,
'ABC345IADX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00021' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla2|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 4 AS RNUM,
'ABC345IAEX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00022' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla3|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 5 AS RNUM,
'ABC345IAFX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00023' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla4|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 6 AS RNUM,
'ABC345IAGX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00024' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla5|Open' AS grp_tsk_type_and_status
FROM DUAL
UNION ALL
SELECT 7 AS RNUM,
'ABC345IAHX' AS ta_or_od_id,
NULL AS lnk_od_id,
'0001' AS bussiness_unit,
'00025' AS CIF,
NULL AS pf_id,
7 AS MAX_ROWNUM,
'Open' AS grp_tsk_status,
'Tesla6|Open' AS grp_tsk_type_and_status
FROM DUAL
)
SELECT DISTINCT b.RNUM as ROW_NUM,
b.MAX_ROWNUM,
b.ta_or_od_id,
b.lnk_od_id,
b.bussiness_unit,
b.CIF,
b.pf_id,
b.grp_tsk_status,
b.grp_tsk_type_and_status,
ta.src_sys,
ta.DUE_DATE_VALUE,
ta.mod_at,
tr.ORDER_ID
FROM new_rows b
JOIN tsk_ref tr on case
when b.lnk_od_id is not null and regexp_like(b.lnk_od_id,
'^' || tr.od_id ||
'_|_' || tr.od_id || '$')
then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
LEFT OUTER JOIN rt_saving_cf rsc
ON rsc.rul_id = tr.rul_id AND (rsc.chn = tr.chn OR rsc.chn = 'ALL') AND
rsc.ex_only = ta.so AND rsc.act = 'Y'
WHERE tr.tsk_id IN (SELECT DISTINCT sl_id
FROM (SELECT tr.tsk_id, tr.pr_tsk_id
FROM new_rows b join tsk_ref tr on case when b.lnk_od_id is not null and
regexp_like(b.lnk_od_id,
'^' || tr.od_id || '_|_' ||
tr.od_id || '$') then 1
when b.lnk_od_id is null and
nvl(tr.od_id, tr.tsk_id) = b.ta_or_od_id
then 1
else 0 end = 1 AND b.bussiness_unit = tr.bussiness_unit AND
NVL(b.pf_id, 'NULL') = NVL(tr.pf_id, 'NULL')
JOIN tsk_act ta ON tr.tsk_id = ta.tsk_id
WHERE TA.tsk_status IN ('Open', 'Rejected')
AND UPPER(TR.pr_id) IN ('MA179234')) UNPIVOT (sl_id FOR COL IN (tsk_id, pr_id)))
ORDER BY b.RNUM, b.ta_or_od_id, ta.DUE_DATE_VALUE ASC NULLS LAST, ta.mod_at DESC;
当我在评论中提到临时表时,我指的是 Oracle 可能会自动为您创建的临时表,如本解释计划开头所示:
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 776 | 32 (7)| 00:00:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D66C5_AADEAE83 | | | | |
| 3 | UNION-ALL | | | | | |
| 4 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
...
创建 Oracle 全局临时表可能是个好主意,但该决定取决于几个因素。全局临时表需要更多的工作来管理对象,包括处理快速变化的对象的统计信息。从好的方面来说,查询将始终相同,这减少了解析时间并使查询更易于管理和调整。
如果此查询每小时只运行一次,并且 CTE 足以帮助提高性能,那么可以对所有内容进行硬编码。如果查询每秒运行 10 次,并造成持续的性能问题,那么您可能应该花时间创建全局临时表。 (或者,您也可以使用 oracle 类型和集合来传递多行数据。)
当您简化并缩小选择范围后,您将需要通过使用实数生成执行计划来进行调整。我推荐
GATHER_PLAN_STATISTICS
或 DBMS_SQLTUNE.REPORT_SQL_MONITOR
。这两个工具产生的结果比单纯的解释计划有用得多。使用结果编辑您的问题,我们可以重新审视该问题。