關於並行的使用,我原來所在研發部門(Real-World Performance)的同事陳煥生已經寫了3篇很是棒的「深刻理解」系列,能夠說並行的精華部分都已經涵蓋。sql
然而,對於大部分SQL開發者和DBA來講,並行的一些最基本的使用方法尚未徹底掌握,我着重介紹一下並行使用的常見問題及注意事項。性能優化
一、何時使用並行? 微信
常見的場景有:session
a)併發
普通SQL最多見的狀況就是大表的全表掃描,還有就是大的索引的快速全掃描(注意,index fast full scan可使用並行,index full scan 不能使用並行)。oracle
須要糾正一個誤區:SQL執行慢就能夠經過使用並行或是增長並行來提升速度。性能
正解:並行可否發揮做用要看SQL的具體執行計劃,好比標量子查詢或是DB link,增大並行帶來的性能提高是微乎其微的!優化
多大的表算大表?spa
至少要百萬級以上記錄的表吧。若是幾億甚至十幾億記錄數的表全表掃描不使用並行,SQL的執行時間會至關長,特別是表在SQL執行的過程當中若是還有其餘session的DML操做的時候。.net
OLTP系統的正常事務通常不會使用大表全掃描的執行計劃,若是有一些統計分析的業務,建議在系統資源相對空閒的時候開啓並行。
b)
用create table As Select建立一張大表,如
create table test parallel 16 as select .... from t1,t2 where .....;
alter table test noparallel;
c)
建立或重建索引
create index idx_test on table_A(name) parallel 8;
alter index idx_test noparallel;
d)
大表收集統計信息,能夠設置並行,如degree=>8
其餘不常見的操做還有表壓縮等,一些比較耗時的分區操做也能夠查查語法,看看是否支持並行操做。
二、並行度的選擇
通常使用2的冪做爲並行度,如二、四、八、16等,正常狀況並行度不要設置過高,建議最多不要超過32。固然,特殊狀況特殊對待,強悍的系統(好比exadata),若是須要很是高的響應速度,並行度再多個幾倍也不是問題。並行高的時候併發就要減小,不然可能會耗光並行資源。
三、並行hint的寫法
一般咱們都會使用hint在SQL級別設置並行,通常不在表上和索引上設置並行度,因此咱們上面並行建立表和索引的例子,後面都伴隨着一個noparallel,若是在建立表或索引時使用了並行,要把它改爲noparallel或parallel 1 :
alter table/index table_name/index_name noparallel/parallel 1;
Hint的寫法在10g和11g+有很大差異,11g+就方便不少。
10g 及如下:
每一個須要並行的表都要指定並行,如 /*+ parallel(a 4) parallel(b 4) */ ,若是SQL涉及的表較多,那麼hint會比較長;若是內聯視圖較多,常常會出來遺漏的狀況。若是某個表沒有指定並行,那麼就只能串行,若是某個大表忘了寫,就會出現性能瓶頸。
11g+:
只要在整個sql的任何一個關鍵字(select、update、insert、delete、merge)後面出現一次parallel(n),那麼整個SQL相關的表,都會使用並行,在寫法上很是的簡潔,並且不會遺漏。如今新開發的應用都應該是11gR2以上了,忘了10g的寫法吧。
注意:
/*+ parallel */ 或 /*+ parallel 8 */是錯誤的並行hint寫法,這些不正確的寫法會致使SQL使用一個比較大的並行度,消耗大量的系統資源。
四、並行DML
DML有4種,INSERT、DELETE、UPDATE還有MERGE,如:
insert /*+ parallel(4) */ into t1 select .... from ....;
這個寫法將會在select部分使用並行度爲4的並行,DML部分的並行並無真正的啓用,DML的並行默認是關閉的,若是須要使用,必須在session級別經過下面命令開啓:
alter session enable parallel dml;--推薦寫法
或者alter session force parallel dml parallel n; --用force的語法,可使下面的dml即便不用parallel的hint,也會使用並行度爲n的並行。
執行這個命令後,才真正開啓了DML的並行。
注意:
開啓了DML的並行後,接下來的DML語句將會產生一個表鎖,在commit以前,當前session 不能對該表作查詢和dml操做,其餘session也不能對該表作DML操做。
因此建議,並行dml語句,應該在語句執行後當即commit; 而後再關閉並行dml,完整的過程應該是:
alter session enable parallel dml;
your dml;
commit;
alter session disable parallel dml;
或者alter session force parallel dml parallel 1;
補充:
parallel 的hint並不能保證sql必定會使用並行,若是優化器認爲sql使用索引更高效,可能會使用索引而不使用並行。若是要確保SQL使用並行,有時可能要結合full 的hint,這種狀況很少見。
本文分享自微信公衆號 - 老虎劉談oracle性能優化(sql_tigerliu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。