无论是教科书还是平常的实践都告诉我们 - “尽量避免用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 = ''
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 = ''
)
)
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 = ''
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 = ''
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 = ''
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 = ''
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 = ''
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"='')
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"='')
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"='')
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"='')
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"(+)='' 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"='' 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"='')
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"='' 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"='')
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"(+)='' AND "TENT"."TEMP_STATUS"(+)<>'ORIGIN' AND
"TENT"."TEMP_STATUS"(+)<>'DELETED')
81 - filter("JTEMP"."PROCESS_ID"(+)='' 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 的话,执行时间下降为秒,逻辑读下降为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"='')
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"='')
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"='')
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"='')
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"(+)='' 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"='' 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"='')
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"='' 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"='')
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"(+)='' AND "TENT"."TEMP_STATUS"(+)<>'ORIGIN' AND
"TENT"."TEMP_STATUS"(+)<>'DELETED')
76 - filter("JTEMP"."PROCESS_ID"(+)='' 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 |
|* | TABLE ACCESS FULL | ANZ_CMF_TEMP | | | ()| :: |
|* 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 |
|* | TABLE ACCESS BY INDEX ROWID | ANZ_CMF_TEMP | | | ()| :: |
|* | INDEX RANGE SCAN | I1_ANZ_CMF_TEMP | | | ()| :: |

|* 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 = ''
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 = ''
)
)
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 = ''
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 = ''
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;

Is "UNION ALL" Always Better Than "UNION"? Watch Out!的更多相关文章

  1. Union比or快 Using UNION is faster when it comes to cases like scan two different column。

    problem: 595. Big Countries A country is big if it has an area of bigger than 3 million square km or ...

  2. SQL Server-聚焦UNIOL ALL/UNION查询(二十三)

    前言 本节我们来看看有关查询中UNION和UNION ALL的问题,简短的内容,深入的理解,Always to review the basics. 初探UNION和UNION ALL 首先我们过一遍 ...

  3. sql union和union all的用法及效率

    UNION指令的目的是将两个SQL语句的结果合并起来.从这个角度来看, 我们会产生这样的感觉,UNION跟JOIN似乎有些许类似,因为这两个指令都可以由多个表格中撷取资料. UNION的一个限制是两个 ...

  4. union和union all用法

    工作中,遇到同事之前写的oracle语句中有一个union all,并且很多地方都用到了.便在网上查了一下用法,以下是自己的理解. union  (联合)将两个或者多个结果集合并. 在使用时,两个结果 ...

  5. 联合体(union)的使用方法及其本质

    转自:http://blog.csdn.net/huqinwei987/article/details/23597091 有些基础知识快淡忘了,所以有必要复习一遍,在不借助课本死知识的前提下做些推理判 ...

  6. C++联合体(union)

    C++的union本质上也是个类,跟struct性质几乎一致但是有一个最大的区别,数据共享内存 说到共享内存就要说下union的内存分配 union的大小是按照union里面的成员内存的最大值而分配的 ...

  7. UNION 和 UNION ALL 区别

    UNION用的比较多union all是直接连接,取到得是所有值,记录可能有重复 union 是取唯一值,记录没有重复 1.UNION 的语法如下: [SQL 语句 1] UNION [SQL 语句 ...

  8. union和union all的区别

    UNION 写一篇联合查询(把前后两个表的查询结果集合在前表中)首先有个为什么需要 相同记录数?? 记错了.应该是union两张表的查询字段数目要一致,字段类型要相似相同的数据类型,至少是相似,可转化 ...

  9. 转:union和union all的区别

    Union因为要进行重复值扫描,所以效率低.如果合并没有刻意要删除重复行,那么就使用Union All  两个要联合的SQL语句 字段个数必须一样,而且字段类型要“相容”(一致): 如果我们需要将两个 ...

随机推荐

  1. JS 提交form表单

    源码实例一:javascript 页面加裁时自动提交表单Form表单:<form method="post" id="myform" action=&qu ...

  2. Office EXCEL VBA数组如何使用

    Excel VBA数组入门教程 1. 前言:不要把VBA数组想的太神秘,它其实就是一组数字而已. 2. 数组的维数: Sub 数组示例()  Dim x As Long, y As Long  Dim ...

  3. Wndows 主进程(Rundll32)已停止工作

        打开电脑,出现"windows 主进程(Rundll32)已停止工作",百度了一下,是文件损坏了.     下载一个新的文件,替换即可,若遇到权限问题,使用魔方工具中的设置 ...

  4. JavaScript 之 特殊运算符

    一.=== 下面的规则用来判断两个值是否===相等:       首先,== equality 等同,=== identity 恒等.       ==, 两边值类型不同的时候,要先进行类型转换,再比 ...

  5. Android 之 Android目录

    Android的目录结构如图所示: 下面来分别说说各个目录: 1.src:存放应用程序中所有的(后台)源代码,代码的源文件一般存放在相应的包下面. 2.gen:该目录下一般有BuildConfig.j ...

  6. iOS禁用系统休眠

    [UIApplicationsharedApplication].idleTimeDisabled= YES

  7. MySQL Cluster线上管理节点配置文件-数据节点32G内存

    网上的朋友提供的,仅供参考. [NDBD DEFAULT] NoOfReplicas= 2 DataMemory=20G IndexMemory=5G MaxNoOfConcurrentTransac ...

  8. spring常用注解以IOC理解

    使用注解来构造IoC容器 用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<context:component-scan base-package ...

  9. 【WebKit内核 CEF3 】 第一篇:下载分支代码并本地编译

    关于CEF  Chromium Embedded Framework 简单说就是  WebKit内核的 对外绑定. 当前主流浏览器内核 一.Trident内核代表产品Internet Explorer ...

  10. 升级openssh基于openssl

    OpenSSH is the premier connectivity tool for remote login with the SSH protocol. It encrypts all tra ...