並行HINT並不一定起作用。

wei-xh發表於2010-07-11

今天又加班,憋屈的要死。

正無聊呢,同事過來問我個問題,為什麼他透過HINT為查詢指定了並行度5,但執行計劃裡卻沒有期待中的並行操作。這小子自從聽我說了有並行這個東西后,對並行簡直著了迷。
原語句如下:
select count(distinct aac001) from ac04;
執行計劃顯示用到了AAC001欄位上的索引,ORACLE為這個語句評估出來的cost是178。


看看採用並行度5的cost是多少。
explain plan for select /*+ full(ac04) parallel(ac04 5) */ count(distinct aac001) from ac04;
發現ORACLE評估出來的cost是431。

 

並行度5的cost 431> 正常索引的cost 178,因此CBO評估出並行的代價比較大,因此沒有采用並行。

我試著加大並行度到10:
explain plan for select /*+ full(ac04) parallel(ac04 10) */ count(distinct aac001) from ac04;
這個時候ORACLE評估出來的cost只有141了。

 

並行度10的cost 141< 正常索引的cost 178,這個時候應該走並行了吧。

然後我讓他按照並行度10進行查詢,看看如何,這個時候ORACLE採用了並行查詢。

其實大著Troubleshooting Oracle Performance 這本書裡對這塊有詳細的說明the query optimizer
considers execution plans with and without parallel processing and, as usual, picks out
the one with the lower cost:

SQL> EXPLAIN PLAN SET STATEMENT_ID 'dop1' FOR
2 SELECT /*+ full(t) parallel(t 1) */ * FROM t WHERE id > 90000;
SQL> EXPLAIN PLAN SET STATEMENT_ID 'dop2' FOR
2 SELECT /*+ full(t) parallel(t 2) */ * FROM t WHERE id > 90000;
SQL> EXPLAIN PLAN SET STATEMENT_ID 'dop3' FOR
2 SELECT /*+ full(t) parallel(t 3) */ * FROM t WHERE id > 90000;
SQL> EXPLAIN PLAN SET STATEMENT_ID 'dop4' FOR
2 SELECT /*+ full(t) parallel(t 4) */ * FROM t WHERE id > 90000;
SQL> SELECT statement_id, cost
2 FROM plan_table
3 WHERE id = 0
4 ORDER BY statement_id;
STATEMENT_ID COST
------------- -----
dop1 430
dop2 238
dop3 159
dop4 119

可以看到隨著並行度的加大,cost在逐漸的變小。再看看正常不加並行的cost
SQL> SELECT * FROM t WHERE id > 9000;
---------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
---------------------------------------------------------
| 0 | SELECT STATEMENT | | 178 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| T | 178 (0)|
| 2 | INDEX RANGE SCAN | I | 24 (0)|
---------------------------------------------------------

 

正常不加並行的cost 178 < 並行度1 和並行度2 時候的cost,因此如果你採用並行度為1或2的時候,並行不會起作用。

SQL> SELECT /*+ parallel(t 2) */ * FROM t WHERE id > 90000;
---------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
---------------------------------------------------------
| 0 | SELECT STATEMENT | | 178 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| T | 178 (0)|
| 2 | INDEX RANGE SCAN | I | 24 (0)|
---------------------------------------------------------

正常不加並行的cost 178 > 並行度3 和並行度4 時候的cost,因此如果你採用並行度為3或4,並行會起作用了。
SQL> SELECT /*+ parallel(t 3) */ * FROM t WHERE id > 90000;
------------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
------------------------------------------------------
| 0 | SELECT STATEMENT | | 159 (0)|
| 1 | PX COORDINATOR | | |
| 2 | PX SEND QC (RANDOM)| :TQ10000 | 159 (0)|
| 3 | PX BLOCK ITERATOR | | 159 (0)|
| 4 | TABLE ACCESS FULL| T | 159 (0)|
------------------------------------------------------

 

還有個小tips跟大家分享,如果正常的查詢,執行計劃中用到了index fast full scan,你如果想使用並行的話,可以透過hint parallel_index來,而不要透過parallel來,後者會選擇全表掃描的。而index range scan就沒辦法了,這個操作是不能並行的,想並行的話貌似只能透過hint parallel,全表掃描來進行並行。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22034023/viewspace-667739/,如需轉載,請註明出處,否則將追究法律責任。

相關文章