zoukankan      html  css  js  c++  java
  • Is "UNION ALL" Always Better Than "UNION"? Watch Out!

    无论是教科书还是平常的实践都告诉我们 - “尽量避免用UNION,尽可能用UNION ALL替代”。 原因很简单,UNION会对结果集进行排序去重操作,这是一个很消耗资源的操作。

    但是,今天碰到了一个SQL (on 11.2.0.3),如果用UNION的话,查询很快就返回结果,逻辑读不是很大。但是如果用UNION ALL的话,查询要很久才有返回,逻辑读非常大。

    SQL如下(注意高亮显示的UNION ALL)

    WITH v_tmp_entity_code AS
    (
        SELECT CHILD_CODE
        FROM
        ( 
            SELECT     child_code,
                    mother_code
            FROM     lo_entity_links_temp
            WHERE     process_id = '11838873'
            AND     temp_status <> 'DELETED'
            AND     purpose      = 'Credit Hierarchy'
            AND     TYPE         = 'Customer Grouping'
          UNION ALL
            SELECT     child_code,
                    mother_code
            FROM     lo_entity_links l
            WHERE     purpose = 'Credit Hierarchy'
            AND     TYPE    = 'Customer Grouping'
            AND NOT EXISTS
            (
                SELECT     NULL
                FROM     lo_entity_links_temp t
                WHERE     l.id       = t.id
                AND     t.process_id = '11838873'
            )
        )
        START WITH MOTHER_CODE      = 568
        CONNECT BY PRIOR child_code = MOTHER_CODE
    )
    SELECT     UP_SUB.ENTITY_CODE AS "ENTITY_CODE",
            UP_SUB.ENTITY_NAME      AS "ENTITY_NAME"
    FROM
      (
      SELECT      EN.ENTITY_CODE,
                DECODE(TA.ATTRIBUTE_6, NULL, EN.ATTRIBUTE_6, TA.ATTRIBUTE_6)                                              AS "ATTRIBUTE_6",
                DECODE(TA.incorporation_country_code, NULL, EN.incorporation_country_code, TA.incorporation_country_code) AS "INCORP_COUNTRY",
                DECODE(TA.LONG_NAME, NULL, EN.LONG_NAME, TA.LONG_NAME)                                                    AS "ENTITY_NAME",
                DECODE( TA.IS_BLACKBOOK, 'T', 1, 0) IS_BLACKBOOK_CP
      FROM         LO_ENTITY EN
      LEFT OUTER JOIN CD_USERS U  ON EN.ATTRIBUTE_7 = U.USER_NAME
      LEFT OUTER JOIN LO_ENTITY_TEMP TA ON EN.ENTITY_CODE   = TA.ENTITY_CODE
                                          AND TA.process_id   = '11838873'
                                          AND TA.TEMP_STATUS <> 'ORIGIN'
                                          AND TA.TEMP_STATUS <> 'DELETED'
                                          AND TA.process_type = 'WORKFLOW'
      WHERE  EN.id IN
        (
            SELECT child_code FROM v_tmp_entity_code
        )
      AND EN.entity_code NOT IN
        (
            SELECT     SUB_ECO.ENTITY_CODE
            FROM     V_TEMP_ANZ_CMF SUB_ECO
            WHERE     SUB_ECO.is_temp    = 'Y'
            AND     SUB_ECO.process_id   = '11838873'
            AND     SUB_ECO.ENTITY_CODE IN
            (
                SELECT TO_CHAR(child_code) FROM v_tmp_entity_code
          )
        )
      ORDER BY EN.LONG_NAME
      ) UP_SUB
    UNION ALL
    SELECT 
            SUPER.ENTITY_CODE AS "ENTITY_CODE",
            SUPER.ENTITY_NAME      AS "ENTITY_NAME"
    FROM
    (
        SELECT     UP_SUB.ENTITY_CODE,
                UP_SUB.COUNTERPARTY_NAME AS "ENTITY_NAME"
        FROM
        (
            SELECT SUB.*
            FROM
            (
                SELECT     DISTINCT 
                        DECODE(TENT.LONG_NAME, NULL, ENT.LONG_NAME, TENT.LONG_NAME) AS "COUNTERPARTY_NAME" ,
                        ENT.ENTITY_CODE,
                        CMF.CMF_ROLE                                                      AS "ROLE",
                        ENT.ATTRIBUTE_7
                FROM     V_TEMP_ANZ_CMF CMF
                LEFT OUTER JOIN LO_ENTITY_TEMP TENT
                    ON CMF.ENTITY_CODE    = TENT.ENTITY_CODE
                    AND TENT.process_id   = '11838873'
                    AND TENT.TEMP_STATUS <> 'ORIGIN'
                    AND TENT.TEMP_STATUS <> 'DELETED'
                LEFT OUTER JOIN LO_ENTITY ENT
                    ON CMF.ENTITY_CODE = ENT.ENTITY_CODE
                LEFT OUTER JOIN LO_ENTITY_TEMP JTEMP
                    ON JTEMP.ENTITY_CODE   = CMF.GRP
                    AND JTEMP.process_id   = '11838873'
                    AND JTEMP.TEMP_STATUS <> 'ORIGIN'
                    AND JTEMP.TEMP_STATUS <> 'DELETED'
                LEFT OUTER JOIN LO_ENTITY JENT
                    ON JENT.ENTITY_CODE  = CMF.GRP
                WHERE      CMF.is_temp      = 'Y'
                AND     CMF.process_id   = '11838873'
                AND     CMF.entity_code IN
                (
                    SELECT TO_CHAR(child_code) FROM v_tmp_entity_code
                )
            ) SUB
            LEFT OUTER JOIN CD_USERS U
            ON SUB.ATTRIBUTE_7 = U.USER_NAME
            ORDER BY 
                DECODE(SUB.ROLE, 'GRP', 1, 'GRP/CP', 2, 'CP', 3, 'AP', 4),
                SUB.ENTITY_CODE
        )UP_SUB
     ) SUPER
     ;
     

    执行计划和统计信息如下,

    Elapsed: 00:00:40.50
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 495744135
    
    --------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                            | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                     |                             |     3 |   387 |  1791  (67)| 00:00:22 |
    |   1 |  TEMP TABLE TRANSFORMATION           |                             |       |       |         |     |
    |   2 |   LOAD AS SELECT                     | SYS_TEMP_0FD9D6FDF_24D7DA10 |       |       |         |     |
    |*  3 |    CONNECT BY WITH FILTERING         |                             |       |       |         |     |
    |   4 |     VIEW                             |                             |     2 |    52 |     8   (0)| 00:00:01 |
    |   5 |      UNION-ALL                       |                             |       |       |         |     |
    |*  6 |       TABLE ACCESS BY INDEX ROWID    | LO_ENTITY_LINKS_TEMP        |     1 |    52 |     3   (0)| 00:00:01 |
    |*  7 |        INDEX RANGE SCAN              | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |   8 |       NESTED LOOPS ANTI              |                             |     1 |    57 |     5   (0)| 00:00:01 |
    |*  9 |        TABLE ACCESS BY INDEX ROWID   | LO_ENTITY_LINKS             |     1 |    45 |     2   (0)| 00:00:01 |
    |* 10 |         INDEX RANGE SCAN             | I1_LO_ENTITY_LINKS          |     1 |       |     1   (0)| 00:00:01 |
    |* 11 |        TABLE ACCESS BY INDEX ROWID   | LO_ENTITY_LINKS_TEMP        |     1 |    12 |     3   (0)| 00:00:01 |
    |* 12 |         INDEX RANGE SCAN             | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  13 |     VIEW                             |                             |     3 |    78 |    27   (4)| 00:00:01 |
    |  14 |      UNION-ALL                       |                             |       |       |         |     |
    |* 15 |       HASH JOIN                      |                             |     1 |    65 |    12   (9)| 00:00:01 |
    |* 16 |        TABLE ACCESS BY INDEX ROWID   | LO_ENTITY_LINKS_TEMP        |     1 |    52 |     3   (0)| 00:00:01 |
    |* 17 |         INDEX RANGE SCAN             | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  18 |        CONNECT BY PUMP               |                             |       |       |         |     |
    |* 19 |       HASH JOIN ANTI                 |                             |     2 |   140 |    16   (7)| 00:00:01 |
    |  20 |        NESTED LOOPS                  |                             |       |       |         |     |
    |  21 |         NESTED LOOPS                 |                             |     2 |   116 |    12   (0)| 00:00:01 |
    |  22 |          CONNECT BY PUMP             |                             |       |       |         |     |
    |* 23 |          INDEX RANGE SCAN            | I1_LO_ENTITY_LINKS          |     1 |       |     1   (0)| 00:00:01 |
    |* 24 |         TABLE ACCESS BY INDEX ROWID  | LO_ENTITY_LINKS             |     1 |    45 |     2   (0)| 00:00:01 |
    |  25 |        TABLE ACCESS BY INDEX ROWID   | LO_ENTITY_LINKS_TEMP        |     1 |    12 |     3   (0)| 00:00:01 |
    |* 26 |         INDEX RANGE SCAN             | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  27 |   UNION-ALL                          |                             |       |       |         |     |
    |  28 |    VIEW                              |                             |     1 |   129 |   602   (1)| 00:00:08 |
    |  29 |     SORT ORDER BY                    |                             |     1 |   105 |   602   (1)| 00:00:08 |
    |* 30 |      HASH JOIN ANTI                  |                             |     1 |   105 |   601   (1)| 00:00:08 |
    |* 31 |       HASH JOIN OUTER                |                             |     1 |    97 |   587   (1)| 00:00:08 |
    |  32 |        NESTED LOOPS                  |                             |       |       |         |     |
    |  33 |         NESTED LOOPS                 |                             |     1 |    55 |     5  (20)| 00:00:01 |
    |  34 |          VIEW                        | VW_NSO_1                    |     5 |    30 |     2   (0)| 00:00:01 |
    |  35 |           HASH UNIQUE                |                             |     1 |    30 |         |     |
    |  36 |            VIEW                      |                             |     5 |    30 |     2   (0)| 00:00:01 |
    |  37 |             TABLE ACCESS FULL        | SYS_TEMP_0FD9D6FDF_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    |* 38 |          INDEX UNIQUE SCAN           | PK_LO_ENTITY                |     1 |       |     1   (0)| 00:00:01 |
    |  39 |         TABLE ACCESS BY INDEX ROWID  | LO_ENTITY                   |     1 |    49 |     2   (0)| 00:00:01 |
    |* 40 |        TABLE ACCESS FULL             | LO_ENTITY_TEMP              |     2 |    84 |   581   (1)| 00:00:07 |
    |  41 |       VIEW                           | VW_NSO_2                    |    15 |   120 |    14  (15)| 00:00:01 |
    |* 42 |        HASH JOIN                     |                             |    15 |   660 |    14  (15)| 00:00:01 |
    |  43 |         VIEW                         | V_TEMP_ANZ_CMF              |     3 |   114 |    11  (10)| 00:00:01 |
    |  44 |          UNION-ALL                   |                             |       |       |         |     |
    |* 45 |           TABLE ACCESS FULL          | ANZ_CMF_TEMP                |     1 |    25 |     3   (0)| 00:00:01 |
    |* 46 |           FILTER                     |                             |       |       |         |     |
    |  47 |            MERGE JOIN CARTESIAN      |                             |     1 |    17 |     5  (20)| 00:00:01 |
    |  48 |             VIEW                     |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |  49 |              HASH UNIQUE             |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 50 |               INDEX RANGE SCAN       | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  51 |             BUFFER SORT              |                             |     1 |     8 |     5  (20)| 00:00:01 |
    |  52 |              TABLE ACCESS FULL       | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |* 53 |            TABLE ACCESS FULL         | ANZ_CMF_TEMP                |     1 |    17 |     3   (0)| 00:00:01 |
    |* 54 |           FILTER                     |                             |       |       |         |     |
    |  55 |            TABLE ACCESS FULL         | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |  56 |         VIEW                         |                             |     5 |    30 |     2   (0)| 00:00:01 |
    |  57 |          TABLE ACCESS FULL           | SYS_TEMP_0FD9D6FDF_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    |  58 |    VIEW                              |                             |     2 |   258 |  1189   (1)| 00:00:15 |
    |  59 |     SORT ORDER BY                    |                             |     2 |   376 |  1189   (1)| 00:00:15 |
    |  60 |      VIEW                            |                             |     2 |   376 |  1188   (1)| 00:00:15 |
    |  61 |       HASH UNIQUE                    |                             |     2 |   288 |  1188   (1)| 00:00:15 |
    |* 62 |        HASH JOIN                     |                             |    15 |  2160 |  1187   (1)| 00:00:15 |
    |  63 |         NESTED LOOPS OUTER           |                             |     3 |   414 |  1184   (1)| 00:00:15 |
    |  64 |          NESTED LOOPS OUTER          |                             |     3 |   390 |  1181   (1)| 00:00:15 |
    |* 65 |           HASH JOIN OUTER            |                             |     3 |   291 |  1175   (1)| 00:00:15 |
    |* 66 |            HASH JOIN OUTER           |                             |     3 |   231 |   593   (1)| 00:00:08 |
    |  67 |             VIEW                     | V_TEMP_ANZ_CMF              |     3 |   150 |    11  (10)| 00:00:01 |
    |  68 |              UNION-ALL               |                             |       |       |         |     |
    |* 69 |               TABLE ACCESS FULL      | ANZ_CMF_TEMP                |     1 |    37 |     3   (0)| 00:00:01 |
    |* 70 |               FILTER                 |                             |       |       |         |     |
    |  71 |                MERGE JOIN CARTESIAN  |                             |     1 |    29 |     5  (20)| 00:00:01 |
    |  72 |                 VIEW                 |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |  73 |                  HASH UNIQUE         |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 74 |                   INDEX RANGE SCAN   | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  75 |                 BUFFER SORT          |                             |     1 |    20 |     5  (20)| 00:00:01 |
    |  76 |                  TABLE ACCESS FULL   | ANZ_CMF                     |     1 |    20 |     3   (0)| 00:00:01 |
    |* 77 |                TABLE ACCESS FULL     | ANZ_CMF_TEMP                |     1 |    17 |     3   (0)| 00:00:01 |
    |* 78 |               FILTER                 |                             |       |       |         |     |
    |  79 |                TABLE ACCESS FULL     | ANZ_CMF                     |     1 |    20 |     3   (0)| 00:00:01 |
    |* 80 |             TABLE ACCESS FULL        | LO_ENTITY_TEMP              |     2 |    54 |   581   (1)| 00:00:07 |
    |* 81 |            TABLE ACCESS FULL         | LO_ENTITY_TEMP              |     2 |    40 |   581   (1)| 00:00:07 |
    |  82 |           TABLE ACCESS BY INDEX ROWID| LO_ENTITY                   |     1 |    33 |     2   (0)| 00:00:01 |
    |* 83 |            INDEX UNIQUE SCAN         | I6_LO_ENTITY                |     1 |       |     1   (0)| 00:00:01 |
    |* 84 |          INDEX UNIQUE SCAN           | I6_LO_ENTITY                |     1 |     8 |     1   (0)| 00:00:01 |
    |  85 |         VIEW                         |                             |     5 |    30 |     2   (0)| 00:00:01 |
    |  86 |          TABLE ACCESS FULL           | SYS_TEMP_0FD9D6FDF_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    --------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       3 - access("MOTHER_CODE"=PRIOR "CHILD_CODE")
       6 - filter("MOTHER_CODE"=568 AND "TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy' AND
                  "TEMP_STATUS"<>'DELETED')
       7 - access("PROCESS_ID"='11838873')
       9 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy')
      10 - access("MOTHER_CODE"=568)
      11 - filter("L"."ID"="T"."ID")
      12 - access("T"."PROCESS_ID"='11838873')
      15 - access("connect$_by$_pump$_005"."PRIOR child_code "="MOTHER_CODE")
      16 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy' AND "TEMP_STATUS"<>'DELETED')
      17 - access("PROCESS_ID"='11838873')
      19 - access("L"."ID"="T"."ID")
      23 - access("connect$_by$_pump$_005"."PRIOR child_code "="MOTHER_CODE")
      24 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy')
      26 - access("T"."PROCESS_ID"='11838873')
      30 - access("EN"."ENTITY_CODE"="ENTITY_CODE")
      31 - access("EN"."ENTITY_CODE"="TA"."ENTITY_CODE"(+))
      38 - access("EN"."ID"="CHILD_CODE")
      40 - filter("TA"."PROCESS_ID"(+)='11838873' AND "TA"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "TA"."TEMP_STATUS"(+)<>'DELETED' AND "TA"."PROCESS_TYPE"(+)='WORKFLOW')
      42 - access("SUB_ECO"."ENTITY_CODE"=TO_CHAR("CHILD_CODE"))
      45 - filter("PROCESS_ID"='11838873' AND "TEMP_STATUS"<>'DELETED')
      46 - filter( NOT EXISTS (SELECT 0 FROM RO_ANZ_CI."ANZ_CMF_TEMP" "ANZ_CMF_TEMP" WHERE "PROCESS_ID"=:B1 AND
                  "ENTITY_CODE"=:B2))
      50 - access("PROCESS_ID"='11838873')
      53 - filter("PROCESS_ID"=:B1 AND "ENTITY_CODE"=:B2)
      54 - filter(NULL IS NOT NULL AND NULL IS NOT NULL)
      62 - access("CMF"."ENTITY_CODE"=TO_CHAR("CHILD_CODE"))
      65 - access("JTEMP"."ENTITY_CODE"(+)="CMF"."GRP")
      66 - access("CMF"."ENTITY_CODE"="TENT"."ENTITY_CODE"(+))
      69 - filter("PROCESS_ID"='11838873' AND "TEMP_STATUS"<>'DELETED')
      70 - filter( NOT EXISTS (SELECT 0 FROM RO_ANZ_CI."ANZ_CMF_TEMP" "ANZ_CMF_TEMP" WHERE "PROCESS_ID"=:B1 AND
                  "ENTITY_CODE"=:B2))
      74 - access("PROCESS_ID"='11838873')
      77 - filter("PROCESS_ID"=:B1 AND "ENTITY_CODE"=:B2)
      78 - filter(NULL IS NOT NULL AND NULL IS NOT NULL)
      80 - filter("TENT"."PROCESS_ID"(+)='11838873' AND "TENT"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "TENT"."TEMP_STATUS"(+)<>'DELETED')
      81 - filter("JTEMP"."PROCESS_ID"(+)='11838873' AND "JTEMP"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "JTEMP"."TEMP_STATUS"(+)<>'DELETED')
      83 - access("CMF"."ENTITY_CODE"="ENT"."ENTITY_CODE"(+))
      84 - access("JENT"."ENTITY_CODE"(+)="CMF"."GRP")
    
    
    Statistics
    ----------------------------------------------------------
             59  recursive calls
          22053  db block gets
        5642276  consistent gets
              1  physical reads
            676  redo size
            667  bytes sent via SQL*Net to client
            499  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              8  sorts (memory)
              0  sorts (disk)
              2  rows processed
    
    SQL>

    先不看至今计划,单看执行时间 - 大约40秒,逻辑读 5,642,276

    如果把UNION ALL 改成 UNION 的话,执行时间下降为2秒,逻辑读下降为106,830 !

    Elapsed: 00:00:02.04
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 1306395122
    
    ----------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                              | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                       |                             |    20 |  3350 |  1863  (66)| 00:00:23 |
    |   1 |  TEMP TABLE TRANSFORMATION             |                             |       |       |         |             |
    |   2 |   LOAD AS SELECT                       | SYS_TEMP_0FD9D6FE3_24D7DA10 |       |       |         |             |
    |*  3 |    CONNECT BY WITH FILTERING           |                             |       |       |         |             |
    |   4 |     VIEW                               |                             |     2 |    52 |     8   (0)| 00:00:01 |
    |   5 |      UNION-ALL                         |                             |       |       |         |             |
    |*  6 |       TABLE ACCESS BY INDEX ROWID      | LO_ENTITY_LINKS_TEMP        |     1 |    52 |     3   (0)| 00:00:01 |
    |*  7 |        INDEX RANGE SCAN                | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |   8 |       NESTED LOOPS ANTI                |                             |     1 |    57 |     5   (0)| 00:00:01 |
    |*  9 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY_LINKS             |     1 |    45 |     2   (0)| 00:00:01 |
    |* 10 |         INDEX RANGE SCAN               | I1_LO_ENTITY_LINKS          |     1 |       |     1   (0)| 00:00:01 |
    |* 11 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY_LINKS_TEMP        |     1 |    12 |     3   (0)| 00:00:01 |
    |* 12 |         INDEX RANGE SCAN               | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  13 |     VIEW                               |                             |     3 |    78 |    27   (4)| 00:00:01 |
    |  14 |      UNION-ALL                         |                             |       |       |         |             |
    |* 15 |       HASH JOIN                        |                             |     1 |    65 |    12   (9)| 00:00:01 |
    |* 16 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY_LINKS_TEMP        |     1 |    52 |     3   (0)| 00:00:01 |
    |* 17 |         INDEX RANGE SCAN               | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  18 |        CONNECT BY PUMP                 |                             |       |       |         |             |
    |* 19 |       HASH JOIN ANTI                   |                             |     2 |   140 |    16   (7)| 00:00:01 |
    |  20 |        NESTED LOOPS                    |                             |       |       |         |             |
    |  21 |         NESTED LOOPS                   |                             |     2 |   116 |    12   (0)| 00:00:01 |
    |  22 |          CONNECT BY PUMP               |                             |       |       |         |             |
    |* 23 |          INDEX RANGE SCAN              | I1_LO_ENTITY_LINKS          |     1 |       |     1   (0)| 00:00:01 |
    |* 24 |         TABLE ACCESS BY INDEX ROWID    | LO_ENTITY_LINKS             |     1 |    45 |     2   (0)| 00:00:01 |
    |  25 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY_LINKS_TEMP        |     1 |    12 |     3   (0)| 00:00:01 |
    |* 26 |         INDEX RANGE SCAN               | LINKS_TEMP                  |     1 |       |     1   (0)| 00:00:01 |
    |  27 |   SORT UNIQUE                          |                             |    20 |  3350 |  1863  (66)| 00:00:23 |
    |  28 |    UNION-ALL                           |                             |       |       |         |             |
    |* 29 |     HASH JOIN ANTI                     |                             |     5 |   575 |   641   (1)| 00:00:08 |
    |* 30 |      HASH JOIN OUTER                   |                             |     5 |   440 |   594   (1)| 00:00:08 |
    |  31 |       NESTED LOOPS                     |                             |       |       |         |             |
    |  32 |        NESTED LOOPS                    |                             |     5 |   260 |    12   (0)| 00:00:01 |
    |  33 |         VIEW                           |                             |     5 |    65 |     2   (0)| 00:00:01 |
    |  34 |          TABLE ACCESS FULL             | SYS_TEMP_0FD9D6FE3_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    |* 35 |         INDEX UNIQUE SCAN              | PK_LO_ENTITY                |     1 |       |     1   (0)| 00:00:01 |
    |  36 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY                   |     1 |    39 |     2   (0)| 00:00:01 |
    |* 37 |       TABLE ACCESS FULL                | LO_ENTITY_TEMP              |     2 |    72 |   581   (1)| 00:00:07 |
    |  38 |      VIEW                              | VW_NSO_1                    |    15 |   405 |    47   (5)| 00:00:01 |
    |* 39 |       HASH JOIN                        |                             |    15 |  1050 |    47   (5)| 00:00:01 |
    |  40 |        VIEW                            | V_TEMP_ANZ_CMF              |     3 |   171 |    44   (3)| 00:00:01 |
    |  41 |         UNION-ALL                      |                             |       |       |         |             |
    |* 42 |          TABLE ACCESS FULL             | ANZ_CMF_TEMP                |     1 |    25 |     3   (0)| 00:00:01 |
    |* 43 |          FILTER                        |                             |       |       |         |             |
    |  44 |           MERGE JOIN CARTESIAN         |                             |     1 |    35 |     5  (20)| 00:00:01 |
    |  45 |            VIEW                        |                             |     1 |    27 |     2  (50)| 00:00:01 |
    |  46 |             HASH UNIQUE                |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 47 |              INDEX RANGE SCAN          | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  48 |            BUFFER SORT                 |                             |     1 |     8 |     5  (20)| 00:00:01 |
    |  49 |             TABLE ACCESS FULL          | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |* 50 |           TABLE ACCESS BY INDEX ROWID  | ANZ_CMF_TEMP                |     1 |    17 |    36   (0)| 00:00:01 |
    |* 51 |            INDEX RANGE SCAN            | I1_ANZ_CMF_TEMP             |    41 |       |     1   (0)| 00:00:01 |
    |* 52 |          FILTER                        |                             |       |       |         |             |
    |  53 |           TABLE ACCESS FULL            | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |  54 |        VIEW                            |                             |     5 |    65 |     2   (0)| 00:00:01 |
    |  55 |         TABLE ACCESS FULL              | SYS_TEMP_0FD9D6FE3_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    |* 56 |     HASH JOIN                          |                             |    15 |  2775 |  1220   (1)| 00:00:15 |
    |  57 |      NESTED LOOPS OUTER                |                             |     3 |   516 |  1217   (1)| 00:00:15 |
    |  58 |       NESTED LOOPS OUTER               |                             |     3 |   492 |  1214   (1)| 00:00:15 |
    |* 59 |        HASH JOIN OUTER                 |                             |     3 |   393 |  1208   (1)| 00:00:15 |
    |* 60 |         HASH JOIN OUTER                |                             |     3 |   333 |   626   (1)| 00:00:08 |
    |  61 |          VIEW                          | V_TEMP_ANZ_CMF              |     3 |   252 |    44   (3)| 00:00:01 |
    |  62 |           UNION-ALL                    |                             |       |       |         |             |
    |* 63 |            TABLE ACCESS FULL           | ANZ_CMF_TEMP                |     1 |    37 |     3   (0)| 00:00:01 |
    |* 64 |            FILTER                      |                             |       |       |         |             |
    |  65 |             MERGE JOIN CARTESIAN       |                             |     1 |    47 |     5  (20)| 00:00:01 |
    |  66 |              VIEW                      |                             |     1 |    27 |     2  (50)| 00:00:01 |
    |  67 |               HASH UNIQUE              |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 68 |                INDEX RANGE SCAN        | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  69 |              BUFFER SORT               |                             |     1 |    20 |     5  (20)| 00:00:01 |
    |  70 |               TABLE ACCESS FULL        | ANZ_CMF                     |     1 |    20 |     3   (0)| 00:00:01 |
    |* 71 |             TABLE ACCESS BY INDEX ROWID| ANZ_CMF_TEMP                |     1 |    17 |    36   (0)| 00:00:01 |
    |* 72 |              INDEX RANGE SCAN          | I1_ANZ_CMF_TEMP             |    41 |       |     1   (0)| 00:00:01 |
    |* 73 |            FILTER                      |                             |       |       |         |             |
    |  74 |             TABLE ACCESS FULL          | ANZ_CMF                     |     1 |    20 |     3   (0)| 00:00:01 |
    |* 75 |          TABLE ACCESS FULL             | LO_ENTITY_TEMP              |     2 |    54 |   581   (1)| 00:00:07 |
    |* 76 |         TABLE ACCESS FULL              | LO_ENTITY_TEMP              |     2 |    40 |   581   (1)| 00:00:07 |
    |  77 |        TABLE ACCESS BY INDEX ROWID     | LO_ENTITY                   |     1 |    33 |     2   (0)| 00:00:01 |
    |* 78 |         INDEX UNIQUE SCAN              | I6_LO_ENTITY                |     1 |       |     1   (0)| 00:00:01 |
    |* 79 |       INDEX UNIQUE SCAN                | I6_LO_ENTITY                |     1 |     8 |     1   (0)| 00:00:01 |
    |  80 |      VIEW                              |                             |     5 |    65 |     2   (0)| 00:00:01 |
    |  81 |       TABLE ACCESS FULL                | SYS_TEMP_0FD9D6FE3_24D7DA10 |     5 |    30 |     2   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       3 - access("MOTHER_CODE"=PRIOR "CHILD_CODE")
       6 - filter("MOTHER_CODE"=568 AND "TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy' AND
                  "TEMP_STATUS"<>'DELETED')
       7 - access("PROCESS_ID"='11838873')
       9 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy')
      10 - access("MOTHER_CODE"=568)
      11 - filter("L"."ID"="T"."ID")
      12 - access("T"."PROCESS_ID"='11838873')
      15 - access("connect$_by$_pump$_005"."PRIOR child_code "="MOTHER_CODE")
      16 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy' AND "TEMP_STATUS"<>'DELETED')
      17 - access("PROCESS_ID"='11838873')
      19 - access("L"."ID"="T"."ID")
      23 - access("connect$_by$_pump$_005"."PRIOR child_code "="MOTHER_CODE")
      24 - filter("TYPE"='Customer Grouping' AND "PURPOSE"='Credit Hierarchy')
      26 - access("T"."PROCESS_ID"='11838873')
      29 - access("EN"."ENTITY_CODE"="ENTITY_CODE")
      30 - access("EN"."ENTITY_CODE"="TA"."ENTITY_CODE"(+))
      35 - access("EN"."ID"="CHILD_CODE")
      37 - filter("TA"."PROCESS_ID"(+)='11838873' AND "TA"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "TA"."TEMP_STATUS"(+)<>'DELETED' AND "TA"."PROCESS_TYPE"(+)='WORKFLOW')
      39 - access("SUB_ECO"."ENTITY_CODE"=TO_CHAR("CHILD_CODE"))
      42 - filter("PROCESS_ID"='11838873' AND "TEMP_STATUS"<>'DELETED')
      43 - filter( NOT EXISTS (SELECT 0 FROM RO_ANZ_CI."ANZ_CMF_TEMP" "ANZ_CMF_TEMP" WHERE "PROCESS_ID"=:B1 AND
                  "ENTITY_CODE"=:B2))
      47 - access("PROCESS_ID"='11838873')
      50 - filter("ENTITY_CODE"=:B1)
      51 - access("PROCESS_ID"=:B1)
      52 - filter(NULL IS NOT NULL AND NULL IS NOT NULL)
      56 - access("CMF"."ENTITY_CODE"=TO_CHAR("CHILD_CODE"))
      59 - access("JTEMP"."ENTITY_CODE"(+)="CMF"."GRP")
      60 - access("CMF"."ENTITY_CODE"="TENT"."ENTITY_CODE"(+))
      63 - filter("PROCESS_ID"='11838873' AND "TEMP_STATUS"<>'DELETED')
      64 - filter( NOT EXISTS (SELECT 0 FROM RO_ANZ_CI."ANZ_CMF_TEMP" "ANZ_CMF_TEMP" WHERE "PROCESS_ID"=:B1 AND
                  "ENTITY_CODE"=:B2))
      68 - access("PROCESS_ID"='11838873')
      71 - filter("ENTITY_CODE"=:B1)
      72 - access("PROCESS_ID"=:B1)
      73 - filter(NULL IS NOT NULL AND NULL IS NOT NULL)
      75 - filter("TENT"."PROCESS_ID"(+)='11838873' AND "TENT"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "TENT"."TEMP_STATUS"(+)<>'DELETED')
      76 - filter("JTEMP"."PROCESS_ID"(+)='11838873' AND "JTEMP"."TEMP_STATUS"(+)<>'ORIGIN' AND
                  "JTEMP"."TEMP_STATUS"(+)<>'DELETED')
      78 - access("CMF"."ENTITY_CODE"="ENT"."ENTITY_CODE"(+))
      79 - access("JENT"."ENTITY_CODE"(+)="CMF"."GRP")
    
    
    Statistics
    ----------------------------------------------------------
             56  recursive calls
             13  db block gets
         106830  consistent gets
              1  physical reads
           1344  redo size
            667  bytes sent via SQL*Net to client
            499  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              7  sorts (memory)
              0  sorts (disk)
              2  rows processed
    
    SQL>

    很显然,造成执行时间差别这么大的原因在于逻辑读的差别。逻辑读的差别肯定来自于执行计划的差别。比较下两种情况下的执行计划,主要不同在于访问表ANZ_CMF_TEMP的方式不同 - 用UNION ALL的时候没有用索引扫描!

    (1) UNION ALL

    |  43 |         VIEW                         | V_TEMP_ANZ_CMF              |     3 |   114 |    11  (10)| 00:00:01 |
    |  44 |          UNION-ALL                   |                             |       |       |         |     |
    |* 45 |           TABLE ACCESS FULL          | ANZ_CMF_TEMP                |     1 |    25 |     3   (0)| 00:00:01 |
    |* 46 |           FILTER                     |                             |       |       |         |     |
    |  47 |            MERGE JOIN CARTESIAN      |                             |     1 |    17 |     5  (20)| 00:00:01 |
    |  48 |             VIEW                     |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |  49 |              HASH UNIQUE             |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 50 |               INDEX RANGE SCAN       | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  51 |             BUFFER SORT              |                             |     1 |     8 |     5  (20)| 00:00:01 |
    |  52 |              TABLE ACCESS FULL       | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |* 53 |            TABLE ACCESS FULL         | ANZ_CMF_TEMP                |     1 |    17 |     3   (0)| 00:00:01 |
    |* 54 |           FILTER                     |                             |       |       |         |     |
    |  55 |            TABLE ACCESS FULL         | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |

    (2) UNION

    |  40 |        VIEW                            | V_TEMP_ANZ_CMF              |     3 |   171 |    44   (3)| 00:00:01 |
    |  41 |         UNION-ALL                      |                             |       |       |         |             |
    |* 42 |          TABLE ACCESS FULL             | ANZ_CMF_TEMP                |     1 |    25 |     3   (0)| 00:00:01 |
    |* 43 |          FILTER                        |                             |       |       |         |             |
    |  44 |           MERGE JOIN CARTESIAN         |                             |     1 |    35 |     5  (20)| 00:00:01 |
    |  45 |            VIEW                        |                             |     1 |    27 |     2  (50)| 00:00:01 |
    |  46 |             HASH UNIQUE                |                             |     1 |     9 |     2  (50)| 00:00:01 |
    |* 47 |              INDEX RANGE SCAN          | I1_ANZ_CMF_TEMP             |     1 |     9 |     1   (0)| 00:00:01 |
    |  48 |            BUFFER SORT                 |                             |     1 |     8 |     5  (20)| 00:00:01 |
    |  49 |             TABLE ACCESS FULL          | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |
    |* 50 |           TABLE ACCESS BY INDEX ROWID  | ANZ_CMF_TEMP                |     1 |    17 |    36   (0)| 00:00:01 |
    |* 51 |            INDEX RANGE SCAN            | I1_ANZ_CMF_TEMP             |    41 |       |     1   (0)| 00:00:01 |
    |* 52 |          FILTER                        |                             |       |       |         |             |
    |  53 |           TABLE ACCESS FULL            | ANZ_CMF                     |     1 |     8 |     3   (0)| 00:00:01 |

    这个例子告诉我们用UNION ALL去替换UNION的时候要谨防执行计划的改变!

    其实这个SQL如果只是执行UNION (ALL)的上面的SQL,或是下面的SQL都会很慢,因为执行计划都是走了表扫描的方式来访问ANZ_CMP_TEMP。如果要改变执行计划(比如只执行UNION的上面部分)怎么办呢,基于这个例子启发,尝试用了如下的写法(highlight部分),结果执行计划就走了索引扫描。

    WITH v_tmp_entity_code AS
    (
        SELECT CHILD_CODE
        FROM
        ( 
            SELECT     child_code,
                    mother_code
            FROM     lo_entity_links_temp
            WHERE     process_id = '11838873'
            AND     temp_status <> 'DELETED'
            AND     purpose      = 'Credit Hierarchy'
            AND     TYPE         = 'Customer Grouping'
          UNION ALL
            SELECT     child_code,
                    mother_code
            FROM     lo_entity_links l
            WHERE     purpose = 'Credit Hierarchy'
            AND     TYPE    = 'Customer Grouping'
            AND NOT EXISTS
            (
                SELECT     NULL
                FROM     lo_entity_links_temp t
                WHERE     l.id       = t.id
                AND     t.process_id = '11838873'
            )
        )
        START WITH MOTHER_CODE      = 568
        CONNECT BY PRIOR child_code = MOTHER_CODE
    )
    SELECT     UP_SUB.ENTITY_CODE AS "ENTITY_CODE",
            UP_SUB.ENTITY_NAME      AS "ENTITY_NAME"
    FROM
      (
      SELECT      EN.ENTITY_CODE,
                DECODE(TA.ATTRIBUTE_6, NULL, EN.ATTRIBUTE_6, TA.ATTRIBUTE_6)                                              AS "ATTRIBUTE_6",
                DECODE(TA.incorporation_country_code, NULL, EN.incorporation_country_code, TA.incorporation_country_code) AS "INCORP_COUNTRY",
                DECODE(TA.LONG_NAME, NULL, EN.LONG_NAME, TA.LONG_NAME)                                                    AS "ENTITY_NAME",
                DECODE( TA.IS_BLACKBOOK, 'T', 1, 0) IS_BLACKBOOK_CP
      FROM         LO_ENTITY EN
      LEFT OUTER JOIN CD_USERS U  ON EN.ATTRIBUTE_7 = U.USER_NAME
      LEFT OUTER JOIN LO_ENTITY_TEMP TA ON EN.ENTITY_CODE   = TA.ENTITY_CODE
                                          AND TA.process_id   = '11838873'
                                          AND TA.TEMP_STATUS <> 'ORIGIN'
                                          AND TA.TEMP_STATUS <> 'DELETED'
                                          AND TA.process_type = 'WORKFLOW'
      WHERE  EN.id IN
        (
            SELECT child_code FROM v_tmp_entity_code
        )
      AND EN.entity_code NOT IN
        (
            SELECT     SUB_ECO.ENTITY_CODE
            FROM     V_TEMP_ANZ_CMF SUB_ECO
            WHERE     SUB_ECO.is_temp    = 'Y'
            AND     SUB_ECO.process_id   = '11838873'
            AND     SUB_ECO.ENTITY_CODE IN
            (
                SELECT TO_CHAR(child_code) FROM v_tmp_entity_code
          )
        )
      ORDER BY EN.LONG_NAME
      ) UP_SUB
      UNION 
      SELECT NULL, NULL FROM DUAL WHERE 1=0;
  • 相关阅读:
    webserver服务器
    轮子哥的网站地址
    构建javaweb服务的docker镜像和容器化启动服务
    spring-cloud-alibaba-gateway
    markdown-记笔记常用语法
    java-生成公私钥命令
    阿里云oss文件服务器
    mybatis-mapper.xml一个标签支持执行多个sql语句
    docker安装nacos
    spring-cloud-alibaba-nacos
  • 原文地址:https://www.cnblogs.com/fangwenyu/p/3389993.html
Copyright © 2011-2022 走看看