【sql調優之執行計劃】使用hint(四)Hints for Join
Sql語句的關聯是sql調整的非常重要的一部分,選擇正確的join順序和方式是調優的基礎。
Ordered和leading用來選擇join的順序,ordered就是按照from後面的表名書寫的順序,而leading是將某個(或多個)表的join順序提前。
測試:
SQL> select /*+ */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 453895177
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 7 (15)| 00:00:01 |
|* 2 | HASH JOIN | | 12 | 240 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS FULL| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR")
2 - access("B"."DEPTNO"="C"."DEPTNO")
4 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL>
上面的查詢讓cbo自己選擇最佳的執行計劃,c表和b表先join,使用的是hash join,結果集再與a表hash join。
SQL> select /*+ ordered */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno ;
Execution Plan
----------------------------------------------------------
Plan hash value: 1852559750
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 13 (8)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 13 (8)| 00:00:01 |
| 2 | MERGE JOIN CARTESIAN| | 56 | 1288 | 11 (10)| 00:00:01 |
| 3 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
| 4 | BUFFER SORT | | 4 | 52 | 9 (12)| 00:00:01 |
| 5 | TABLE ACCESS FULL | DEPT | 4 | 52 | 1 (0)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | EMP | 12 | 84 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR" AND "B"."DEPTNO"="C"."DEPTNO")
6 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL>
上面的查詢增加了ordered的hint,使得優化器按照表名書寫順序來連線表(按照從from由近到遠的原則)。由於a和c表並沒有直接聯絡,所以a和c的關聯是merge join cartesian。然後得到的結果集再與b表做hash join。顯然這個做法並不太好。
SQL> select /*+ ordered */a.ename,c.dname from emp b, emp a ,dept c
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 665932159
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 7 (15)| 00:00:01 |
|* 2 | HASH JOIN | | 12 | 204 | 5 (20)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMP | 14 | 140 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."DEPTNO"="C"."DEPTNO")
2 - access("A"."EMPNO"="B"."MGR")
3 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
修改一下b表的位置,放在最前面,則使用ordered以後,表b和表a先做join,然後再與c表join。
SQL>
SQL> select /*+ leading(b) */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 141688920
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 7 (15)| 00:00:01 |
|* 2 | HASH JOIN | | 12 | 240 | 5 (20)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR")
2 - access("B"."DEPTNO"="C"."DEPTNO")
3 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL>
上述查詢使用leading將b表提前,或者也可以使用leading(b.a)將b和a提前join,然後再與c join,得到的結果很顯然應該是與ordered相同。
SQL> select /*+ leading(b,a) */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 665932159
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 7 (15)| 00:00:01 |
|* 2 | HASH JOIN | | 12 | 204 | 5 (20)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMP | 14 | 140 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | DEPT | 4 | 52 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."DEPTNO"="C"."DEPTNO")
2 - access("A"."EMPNO"="B"."MGR")
3 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL>
Use_nl
Use_merge
Use_hash
SQL> select /*+ use_nl(b,c) */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 2135812182
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 8 (13)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 8 (13)| 00:00:01 |
| 2 | NESTED LOOPS | | 12 | 240 | 5 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| EMP | 3 | 21 | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR")
4 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL AND
"B"."DEPTNO"="C"."DEPTNO")
SQL> select /*+ use_merge(b,c) */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 913045500
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 8 (25)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 8 (25)| 00:00:01 |
| 2 | MERGE JOIN | | 12 | 240 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 4 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 5 | SORT JOIN | | 12 | 84 | 3 (34)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 7 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR")
5 - access("B"."DEPTNO"="C"."DEPTNO")
filter("B"."DEPTNO"="C"."DEPTNO")
6 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL> select /*+ use_hash(b,c) */a.ename,c.dname from emp a ,dept c,emp b
2 where a.empno = b.mgr
3 and b.deptno = c.deptno;
Execution Plan
----------------------------------------------------------
Plan hash value: 453895177
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 360 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 12 | 360 | 7 (15)| 00:00:01 |
|* 2 | HASH JOIN | | 12 | 240 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS FULL| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| EMP | 12 | 84 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPNO"="B"."MGR")
2 - access("B"."DEPTNO"="C"."DEPTNO")
4 - filter("B"."MGR" IS NOT NULL AND "B"."DEPTNO" IS NOT NULL)
SQL>
Driving_site
SQL> select * from t_policy a ,t_policy@core b
2 where a.policy_id = b.policy_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 2448822570
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Inst |IN-OUT|
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5027K| 4320M| | 524K (25)| 00:15:39 | | |
|* 1 | HASH JOIN | | 5027K| 4320M| 2113M| 524K (25)| 00:15:39 | | |
| 2 | TABLE ACCESS FULL| T_POLICY | 5025K| 2056M| | 52697 (40)| 00:01:35 | | |
| 3 | REMOTE | T_POLICY | 22M| 9G| | 238K (40)| 00:07:07 | CORE | R->S |
SQL> select /*+ use_nl(a,b)*/* from t_policy a ,t_policy@core b
2 where a.policy_id = b.policy_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 4230146719
--------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |IN-OUT|
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5027K| 4320M| 28M (2)| 14:01:35 | | |
| 1 | NESTED LOOPS | | 5027K| 4320M| 28M (2)| 14:01:35 | | |
| 2 | REMOTE | T_POLICY | 22M| 9G| 238K (40)| 00:07:07 | CORE | R->S |
| 3 | TABLE ACCESS BY INDEX ROWID| T_POLICY | 1 | 429 | 2 (0)| 00:00:01 | | |
|* 4 | INDEX UNIQUE SCAN | IND_POLICY_ID | 1 | | 1 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------
SQL> set autot trace exp
SQL> select /*+ use_nl(a,b) driving_site(b) */* from t_policy a ,t_policy@core b
2 where a.policy_id = b.policy_id;
Execution Plan
----------------------------------------------------------
Error: cannot fetch plan for statement_id 'PLUS684867'
SQL>
SQL> set lines 130
SQL> set pages 1000
SQL> explain plan for
2 select /*+ use_nl(a,b) driving_site(b) */* from t_policy a ,t_policy@core b
3 where a.policy_id = b.policy_id;
Explained.
SQL> select a.operation,substr(a.options,1,30) options,a.object_name from plan_table a ;
select * from table(dbms_xplan.display) a ;
OPERATION OPTIONS OBJECT_NAME
------------------------------ ------------------------------ ------------------------------
SELECT STATEMENT REMOTE
NESTED LOOPS
REMOTE
TABLE ACCESS BY INDEX ROWID T_POLICY
INDEX UNIQUE SCAN PK_T_POLICY
使用driving_site,在分散式查詢的時候,非常有用。
Hash_aj,merge_aj,nl_aj和Hash_sj,merge_sj,nl_sj
Aj為anti-join,用在not in子查詢,sj為semi-join,用在exists 子查詢
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16179598/viewspace-674830/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【sql調優之執行計劃】使用hint(三)Hints for Query TransformationsSQLORM
- 【sql調優之執行計劃】使用hint(二)Hints for Access PathsSQL
- 【sql調優之執行計劃】使用hint(一)Hints for Optimization Approaches and GoalsSQLAPPGo
- 【sql調優之執行計劃】使用hint(五)Hint for parallelSQLParallel
- 【sql調優之執行計劃】hash joinSQL
- 【sql調優之執行計劃】使用hint(六) append and noappendSQLAPP
- 【sql調優之執行計劃】merge sort joinSQL
- 【sql調優之執行計劃】merge semi join and merge anti joinSQL
- 【sql調優之執行計劃】nested loops join and nested loop join outerSQLOOP
- 【sql調優之執行計劃】merge join cartesian and buffer sortSQL
- 【sql調優之執行計劃】獲取執行計劃SQL
- 【sql調優之執行計劃】sort operationsSQL
- 【sql調優之執行計劃】estimator iSQL
- 【sql調優之執行計劃】query transformerSQLORM
- 【sql調優之執行計劃】temp table transformationSQLORM
- 【sql調優之執行計劃】in相關的operationSQL
- mysql調優之——執行計劃explainMySqlAI
- 使用hint改變執行計劃
- 【Oracle】-【索引-HINT,執行計劃】-帶HINT的索引執行計劃Oracle索引
- Oracle調優之看懂Oracle執行計劃Oracle
- 加hint改變執行計劃訪問順序優化sql優化SQL
- 使用Oracle Hint提示來更改執行計劃Oracle
- 使用hint來調優sql語句SQL
- SQL調優(SQL TUNING)並行查詢提示(Hints)之pq_distribute的使用SQL並行
- 使用Oracle Hint提示來更改執行計劃 ZTOracle
- 使用leading(,)優化sql執行計劃優化SQL
- 透過使用hint unnest調優sql語句SQL
- 通過使用hint unnest調優sql語句SQL
- 建立索引調整sql的執行計劃索引SQL
- oracle筆記整理14——效能調優之oracle執行計劃Oracle筆記
- Oracle中SQL調優(SQL TUNING)之最權威獲取SQL執行計劃大全OracleSQL
- 轉摘_使用leading(,)優化sql執行計劃優化SQL
- 使用sql profile固定執行計劃SQL
- 控制執行計劃之-SQL Profile(一)SQL
- sql 執行計劃SQL
- TiDB 查詢優化及調優系列(四)查詢執行計劃的調整及優化原理TiDB優化
- Oracle+高效能SQL引擎剖析:SQL優化與調優機制詳解-筆記之執行計劃(一)OracleSQL優化筆記
- Oracle+高效能SQL引擎剖析:SQL優化與調優機制詳解-筆記之執行計劃(二)OracleSQL優化筆記