在 Join 语句中使用 Select Union From Dual 会降低 Oracle 性能

问题描述 投票:0回答:1

下面的原始查询执行需要 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;

从join语句中的dual中删除大部分select union后的查询:

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;

我想加快查询速度。

sql oracle oracle11g sqlperformance
1个回答
0
投票

使用通用表表达式进行简化

开始调优之前,请使用公用表表达式 (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
。这两个工具产生的结果比单纯的解释计划有用得多。使用结果编辑您的问题,我们可以重新审视该问题。

© www.soinside.com 2019 - 2024. All rights reserved.