Bel*_*lun 6 sql oracle query-optimization
假设一个项目使用分区来构建其数据.这个概念纯粹是针对业务的,与数据库分区无关.
假设业务逻辑确实如此:
请记住,一切都是这样的结构,让问题复杂化(以达到实际问题).
假设我有一个潜在杀手的查询(SELECT查询),就时间而言:
insert into output_table (
select *
from input_table
left outer join additional_table additional_table1
on input_table.id = additional_table1.id
left outer join additional_table additional_table2
on additional_table2.id = additional_table1.parent
where partition = <partitionX>
)
Run Code Online (Sandbox Code Playgroud)
让我们优化它并探索选项.请记住每个表都有分区.另请注意table2如何连接两次,但是在不同的列上.而且,还要注意附加表是如何连接在一起的
一切都使用WITH子句,但有几个选项,我想知道为什么其中一个更好.
A. WITH部分中的直接和重复查询
WITH
CACHED_input_table AS (
SELECT *
FROM input_table
WHERE PARTITION_ID = < partition X >
),
CACHED_additional_table1 AS (
SELECT *
FROM additional_table
WHERE PARTITION_ID = < partition X >
),
CACHED_additional_table2 AS (
SELECT *
FROM additional_table
WHERE PARTITION_ID = < partition X >
)
SELECT *
FROM CACHED_input_table input_table
LEFT OUTER JOIN CACHED_additional_table1 additional_table1
ON input_table.ID = additional_table1.ID
LEFT OUTER JOIN CACHED_additional_table2 additional_table2
ON additional_table1.PARENT_ID = additional_table2.ID
Run Code Online (Sandbox Code Playgroud)
B.在FROM部分中重用查询
WITH
CACHED_input_table AS (
SELECT *
FROM input_table
WHERE PARTITION_ID = < partition X >
),
CACHED_additional_table AS (
SELECT *
FROM additional_table
WHERE PARTITION_ID = < partition X >
)
SELECT *
FROM CACHED_input_table input_table
LEFT OUTER JOIN CACHED_additional_table additional_table1
ON input_table.ID = additional_table1.ID
LEFT OUTER JOIN CACHED_additional_table additional_table2
ON additional_table1.PARENT_ID = additional_table2.ID
Run Code Online (Sandbox Code Playgroud)
C.在WITH部分中重用查询
WITH
CACHED_input_table AS (
SELECT *
FROM input_table
WHERE PARTITION_ID = < partition X >
),
CACHED_additional_table1 AS (
SELECT *
FROM additional_table
WHERE PARTITION_ID = < partition X >
),
CACHED_additional_table2 AS (
SELECT *
FROM CACHED_additional_table1
)
SELECT *
FROM CACHED_input_table input_table
LEFT OUTER JOIN CACHED_additional_table1 additional_table1
ON input_table.ID = additional_table1.ID
LEFT OUTER JOIN CACHED_additional_table2 additional_table2
ON additional_table1.PARENT_ID = additional_table2.ID
Run Code Online (Sandbox Code Playgroud)
根据经验,选项A是最快的.但为什么?有人可以解释一下吗? (我正在使用Oracle v11.2)
我知道,我可能围绕这个公司特定的分区概念进行优化,与我所询问的围绕WITH子句的通用sql优化无关,但请将其作为一个真实的例子.
选项A(7s中9900行)
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1037 | 18540 (8)| 00:00:03 | | |
|* 1 | HASH JOIN OUTER | | 1 | 1037 | 18540 (8)| 00:00:03 | | |
|* 2 | HASH JOIN OUTER | | 1 | 605 | 9271 (8)| 00:00:02 | | |
| 3 | PARTITION LIST SINGLE| | 1 | 173 | 2 (0)| 00:00:01 | KEY | KEY |
| 4 | TABLE ACCESS FULL | input_table | 1 | 173 | 2 (0)| 00:00:01 | 24 | 24 |
| 5 | PARTITION LIST SINGLE| | 1362K| 561M| 9248 (8)| 00:00:02 | KEY | KEY |
| 6 | TABLE ACCESS FULL | additional_table | 1362K| 561M| 9248 (8)| 00:00:02 | 24 | 24 |
| 7 | PARTITION LIST SINGLE | | 1362K| 561M| 9248 (8)| 00:00:02 | KEY | KEY |
| 8 | TABLE ACCESS FULL | additional_table | 1362K| 561M| 9248 (8)| 00:00:02 | 24 | 24 |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("additional_table"."PARENT"="additional_table"."ID"(+))
2 - access("input_table"."ID"="additional_table"."ID"(+))
Run Code Online (Sandbox Code Playgroud)
选项B(10个9900行)
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2813 | 18186 (11)| 00:00:03 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D6CA2_C26AF925 | | | | | | |
| 3 | PARTITION LIST SINGLE | | 1362K| 561M| 9248 (8)| 00:00:02 | KEY | KEY |
| 4 | TABLE ACCESS FULL | additional_table1 | 1362K| 561M| 9248 (8)| 00:00:02 | 24 | 24 |
|* 5 | HASH JOIN OUTER | | 1 | 2813 | 8939 (15)| 00:00:02 | | |
|* 6 | HASH JOIN OUTER | | 1 | 1493 | 4470 (15)| 00:00:01 | | |
| 7 | PARTITION LIST SINGLE | | 1 | 173 | 2 (0)| 00:00:01 | KEY | KEY |
| 8 | TABLE ACCESS FULL | input_table | 1 | 173 | 2 (0)| 00:00:01 | 24 | 24 |
| 9 | VIEW | | 1362K| 1714M| 4447 (14)| 00:00:01 | | |
| 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6CA2_C26AF925 | 1362K| 561M| 4447 (14)| 00:00:01 | | |
| 11 | VIEW | | 1362K| 1714M| 4447 (14)| 00:00:01 | | |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6CA2_C26AF925 | 1362K| 561M| 4447 (14)| 00:00:01 | | |
---------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("additional_table1"."PARENT"="additional_table2"."ID"(+))
6 - access("input_table"."ID"="additional_table1"."ID"(+))
Run Code Online (Sandbox Code Playgroud)
选项C(17s内9900行)
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2813 | 18186 (11)| 00:00:03 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D6CA7_C26AF925 | | | | | | |
| 3 | PARTITION LIST SINGLE | | 1362K| 561M| 9248 (8)| 00:00:02 | KEY | KEY |
| 4 | TABLE ACCESS FULL | additional_table | 1362K| 561M| 9248 (8)| 00:00:02 | 24 | 24 |
|* 5 | HASH JOIN OUTER | | 1 | 2813 | 8939 (15)| 00:00:02 | | |
|* 6 | HASH JOIN OUTER | | 1 | 1493 | 4470 (15)| 00:00:01 | | |
| 7 | PARTITION LIST SINGLE | | 1 | 173 | 2 (0)| 00:00:01 | KEY | KEY |
| 8 | TABLE ACCESS FULL | input_table | 1 | 173 | 2 (0)| 00:00:01 | 24 | 24 |
| 9 | VIEW | | 1362K| 1714M| 4447 (14)| 00:00:01 | | |
| 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6CA7_C26AF925 | 1362K| 561M| 4447 (14)| 00:00:01 | | |
| 11 | VIEW | | 1362K| 1714M| 4447 (14)| 00:00:01 | | |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6CA7_C26AF925 | 1362K| 561M| 4447 (14)| 00:00:01 | | |
---------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("additional_table1"."PARENT_ID"="CACHED_additional_table"."ID"(+))
6 - access("input_table"."ID"="additional_table1"."ID"(+))
Run Code Online (Sandbox Code Playgroud)
编辑: