關于并行的使用,我原來所在研發部門(Real-World Performance)的同僚陳煥生已經寫了3篇非常棒的“深入了解”系列,可以說并行的精華部分都已經涵蓋。
然而,對于大部分SQL開發者和DBA來說,并行的一些最基本的使用方法還沒有完全掌握,我着重介紹一下并行使用的常見問題及注意事項。
1、什麼時候使用并行?
常見的場景有:
a)
普通SQL最常見的情況就是大表的全表掃描,還有就是大的索引的快速全掃描(注意,index fast full scan可以使用并行,index full scan 不能使用并行)。
需要糾正一個誤區:SQL執行慢就可以通過使用并行或是增加并行來提高速度。
正解:并行能否發揮作用要看SQL的具體執行計劃,比如标量子查詢或是DB link,增大并行帶來的性能提升是微乎其微的!
多大的表算大表?
至少要百萬級以上記錄的表吧。如果幾億甚至十幾億記錄數的表全表掃描不使用并行,SQL的執行時間會相當長,特别是表在SQL執行的過程中如果還有其他session的DML操作的時候。
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、并行度的選擇
一般使用2的幂作為并行度,如2、4、8、16等,正常情況并行度不要設定太高,建議最多不要超過32。當然,特殊情況特殊對待,強悍的系統(比如exadata),如果需要非常高的響應速度,并行度再多個幾倍也不是問題。并行高的時候并發就要減少,否則可能會耗光并行資源。
3、并行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使用一個比較大的并行度,消耗大量的系統資源。
4、并行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,這種情況不多見。