轉載:http://czmmiao.iteye.com/blog/1487568html
並行(Parallel)和OLAP系統
並行的實現機制是:首先,Oracle會建立一個進程用於協調並行服務進程之間的信息傳遞,這個協調進程將須要操做的數據集(好比表的數據塊)分割成不少部分,稱爲並行處理單元,而後並行協調進程給每一個並行進程分配一個數據單元。好比有四個並行服務進程,他們就會同時處理各自分配的單元,當一個並行服務進程處理完畢後,協調進程就會給它們分配另外的單元,如此反覆,直到表上的數據都處理完畢,最後協調進程負責將每一個小的集合合併爲一個大集合做爲最終的執行結果,返回給用戶。
並行處理的機制實際上就是把一個要掃描的數據集分紅不少小數據集,Oracle會啓動幾個並行服務進程同時處理這些小數據集,最後將這些結果彙總,做爲最終的處理結果返回給用戶。
這種數據並行處理方式在OLAP系統中很是有用,OLAP系統的表一般來講都是很是大,若是系統的CPU比較多,讓全部的CPU共同來處理這些數據,效果就會比串行執行要高得多。
然而對於OLTP系統,一般來說,並行並不合適,緣由是OLTP系統上幾乎在全部的SQL操做中,數據訪問路徑基本上以索引訪問爲主,而且返回結果集很是小,這樣的SQL操做的處理速度通常很是快,不須要啓用並行。
並行處理的機制
當Oracle數據庫啓動的時候,實例會根據初始化參數 PARALLEL_MIN_SERVERS=n的值來預先分配n個並行服務進程,當一條SQL被CBO判斷爲須要並行執行時發出SQL的會話進程變成並行協助進程,它按照並行執行度的值來分配進程服務器進程。
首先協調進程會使用ORACLE啓動時根據參數: parallel_min_servers=n的值啓動相應的並行服務進程,若是啓動的並行服務器進程數不足以知足並行度要求的並行服務進程數,則並行協調進程將額外啓動並行服務進程以提供更多的並行服務進程來知足執行的需求。而後並行協調進程將要處理的對象劃分紅小數據片,分給並行服務進程處理;並行服務進程處理完畢後將結果發送給並行協調進程,而後由並行協調進程將處理結果彙總併發送給用戶。
剛纔講述的是一個並行處理的基本流程。實際上,在一個並行執行的過程當中,還存在着並行服務進程之間的通訊問題。
在一個並行服務進程須要作兩件事情的時候,它會再啓用一個進程來配合當前的進程完成一個工做,好比這樣的一條SQL語句:
Select * from employees order by last_name;
假設employees表中last_name列上沒有索引,而且並行度爲4,此時並行協調進程會分配4個並行服務進程對錶employees進行全表掃描操做,由於須要對結果集進行排序,因此並行協調進程會額外啓用4個並行服務進程,用於處理4個進程傳送過來的數據,這新啓用的用戶處理傳遞過來數據的進程稱爲父進程,用戶傳出數據(最初的4個並行服務進程)稱爲子進程,這樣整個並行處理過程就啓用了8個並行服務進程。 其中每一個單獨的並行服務進程的行爲叫做並行的內部操做,而並行服務進程之間的數據交流叫作並行的交互操做。
這也是有時咱們發現並行服務進程數量是並行度的2倍,就是由於啓動了並行服務父進程操做的緣故。
讀懂一個並行處理的執行計劃
CREATE TABLE emp2 AS SELECT * FROM employees;
ALTER TABLE emp2 PARALLEL 2;
EXPLAIN PLAN FOR SELECT SUM(salary) FROM emp2 GROUP BY department_id;
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------
Plan hash value: 3939201228
------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 2782 | 3 (34)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 107 | 2782 | 3 (34)| 00:00:01 | Q1,01 | P->S | QC (RAND) |
| 3 | HASH GROUP BY | | 107 | 2782 | 3 (34)| 00:00:01 | Q1,01 | PCWP | |
| 4 | PX RECEIVE | | 107 | 2782 | 3 (34)| 00:00:01 | Q1,01 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | 107 | 2782 | 3 (34)| 00:00:01 | Q1,00 | P->P | HASH |
| 6 | HASH GROUP BY | | 107 | 2782 | 3 (34)| 00:00:01 | Q1,00 | PCWP | |
| 7 | PX BLOCK ITERATOR | | 107 | 2782 | 2 (0)| 00:00:01 | Q1,00 | PCWC | |
| 8 | TABLE ACCESS FULL| EMP2 | 107 | 2782 | 2 (0)| 00:00:01 | Q1,00 | PCWP | |
------------------------------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
19 rows selected.
經過執行計劃,咱們來看一下它的執行步驟:
一、並行服務進程對EMP2表進行全表掃描。
二、並行服務進程以ITERATOR(迭代)方式訪問數據塊,也就是並行協調進程分給每一個並行服務進程一個數據片,在這個數據片上,並行服務進程順序地訪問每一個數據塊(Iterator),全部的並行服務進程將掃描的數據塊傳給另外一組並行服務進程(父進程)用於作Hash Group操做。
三、並行服務父進程對子進程傳遞過來的數據作Hash Group操做。
四、並行服務進程(子進程)將處理完的數據發送出去。
五、並行服務進程(父進程)接收處處理過的數據。
六、合併處理過的數據,按照隨機的順序發給並行協調進程(QC:Query Conordinator)。
七、並行協調進程將處理結果發給用戶。
當使用了並行執行,SQL的執行計劃中就會多出一列:in-out。 該列幫助咱們理解數據流的執行方法。 它的一些值的含義以下:
Parallel to Serial(P->S): 表示一個並行操做發送數據給一個串行操做
Parallel to Parallel(P->P):表示一個並行操做向另外一個並行操做發送數據
Parallel Combined with parent(PCWP): 同一個從屬進程執行的並行操做,同時父操做也是並行的。
Parallel Combined with Child(PCWC): 同一個從屬進程執行的並行操做,子操做也是並行的。
Serial to Parallel(S->P): 一個串行操做發送數據給並行操做,若是select部分是串行操做,就會出現這個狀況。
並行執行等待事件
在作並行執行方面的性能優化的時候,可能會遇到以下等待事件
PX Deq Credit: send blkd
這是一個有並行環境的數據庫中,從statspack 或者AWR中常常能夠看到的等待事件。 在Oracle 9i 裏面, 這個等待時間被列入空閒等待。
通常來講空閒等待能夠忽略它,可是實際上空閒等待也是須要關注的,由於一個空閒的等待,它反映的是另外的資源已經超負荷運行了。基於這個緣由,在Oracle 10g裏已經把PX Deq Credit: send blkd等待時間再也不視爲空閒等待,而是列入了Others 等待事件範圍。
PX Deq Credit: send blkd 等待事件的意思是:當並行服務進程向並行協調進程QC(也多是上一層的並行服務進程)發送消息時,同一時間只有一個並行服務進程能夠向上層進程發送消息,這時候若是有其餘的並行服務進程也要發送消息,就只能等待了。直到得到一個發送消息的信用信息(Credit),這時候會觸發這個等待事件,這個等待事件的超時時間爲2秒鐘。
若是咱們啓動了太多的並行進程,實際上系統資源(CPU)或者QC 沒法即時處理並行服務發送的數據,那麼等待將不可避免。 對於這種狀況,咱們就須要下降並行處理的並行度。
當出現PX Deq Credit:send blkd等待的時間很長時,咱們能夠經過平均等待時間來判斷等待事件是否是下層的並行服務進程空閒形成的。該等待事件的超時時間是2秒,若是平均等待時間也差很少是2秒,就說明是下層的並行進程「無事所作」,處於空閒狀態。 若是和2秒的差距很大,就說明不是下層並行服務超時致使的空閒等待,而是並行服務之間的競爭致使的,由於這個平均等待事件很是短,說明並行服務進程在很短期的等待以後就能夠獲取資源來處理數據。
因此對於非下層的並行進程形成的等待,解決的方法就是下降每一個並行執行的並行度,好比對象(表,索引)上預設的並行度或者查詢Hint 指定的並行度。
並行執行的使用範圍
Parallel Query( 並行查詢 )
並行查詢能夠在查詢語句,子查詢語句中使用,可是不可使用在一個遠程引用的對象上(如DBLINK)。
一個查詢可以並行執行,須要知足如下條件
一、SQL語句中有Hint提示,好比Parallel或者Parallel_index。
二、SQL語句中引用的對象被設置了並行屬性。
三、多表關聯中,至少有一個表執行全表掃描(Full table scan)或者跨分區的Index range SCAN。 如:
select /*+parallel(t 4)×/ * from t;
Parallel DDL(並行DDL操做,如建表,建索引等)
表的並行操做
CREATE TABLE table_name parallel 4 AS SELECT ....
ALTER TABLE table_name move partition partition_name parallel 4;
Alter table table_name split partition partition_name ...... parallel 4;
Alter table table_name coalesce partition parallel 4;
DDL操做,咱們能夠經過trace 文件來查看它的執行過程。
alter session set events '10046 trace name context forever,level 12';
alter session set events '10046 trace name context off' ;
建立索引的並行執行
建立索引時使用並行方式在系統資源充足的時候會使性能獲得很大的提升,特別是在OLAP系統上對一些很大的表建立索引時更是如此。 如下的建立和更改索引的操做均可以使用並行:
Create index index_name on table_name(colum_name) parallel 4;
Alter index index_name rebuild parallel 4
Alter index index_name rebuild partition partition_name parallel 4;
Alter index index_name split partition partition_name .... parallel 4;
注意:索引上的並行度只有在訪問索引的時候才能夠被使用。
總結:
使用並行方式,不管是建立表,修改表,建立索引,重建索引,他們的機制都是同樣的,那就是Oracle 給每一個並行服務進程分配一塊空間,每一個進程在本身的空間裏處理數據,最後將處理完畢的數據彙總,完成SQL的操做。
Parallel DML(並行DML操做,如insert,update,delete等)
Oracle 能夠對DML操做使用並行執行,可是有不少限制。 若是咱們要讓DML操做使用並行執行,必須顯示地在會話裏執行以下命令:
SQL> alter session enable parallel dml;
會話已更改。
只有執行了這個操做,Oracle 纔會對以後符合並行條件的DML操做並行執行,若是沒有這個設定,即便SQL中指定了並行執行,Oracle也會忽略它。
delete,update和merge樣例以下
delete /*+ parallel(table_name 4) */ from test;
update/*+ parallel(table_name 4) */ test set id=100;
merge /*+ parallel(table_name 4) */ into table_name ...
Oracle 對Delete,update,merge的操做限制在,只有操做的對象是分區表示,Oracle纔會啓動並行操做。緣由在於,對於分區表,Oracle 會對每一個分區啓用一個並行服務進程同時進行數據處理,這對於非分區表來講是沒有意義的。 分區表的並行屬性只能在表級別設置,不能在分區級別設置。
注:經筆者測試中非分區表下, Delete,update,merge也能夠執行並行操做,不知道是版本緣由仍是其餘緣由,待考證
Insert 的並行操做
實際上只有對於insert into … select … 這樣的SQL語句啓用並行纔有意義。 對於insert into .. values… 並行沒有意義,由於這條語句自己就是一個單條記錄的操做。
Insert 並行經常使用的語法是:
Insert /*+parallel(t 2) */ into t select /*+parallel(t1 2) */ * from t1;
這條SQL 語句中,可讓兩個操做insert 和select 分別使用並行,這兩個並行是相互獨立,互補干涉的,也能夠單獨使用其中的一個並行。 也有以下語法
Insert into t select /*+parallel(t1 2) */ * from t1;
Insert /*+parallel(t 2) */ into t select * from t1;
並行執行的設定
並行相關的初始話參數
parallel_min_servers=n
在初始化參數中設置了這個值,Oracle 在啓動的時候就會預先啓動N個並行服務進程,當SQL執行並行操做時,並行協調進程首先根據並行度的值,在當前已經啓動的並行服務中條用n個並行服務進程,當並行度大於n時,Oracle將啓動額外的並行服務進程以知足並行度要求的並行服務進程數量。
parallel_max_servers=n
若是並行度的值大於parallel_min_servers或者當前可用的並行服務進程不能知足SQL的並行執行要求,Oracle將額外建立新的並行服務進程,當前實例總共啓動的並行服務進程不能超過這個參數的設定值。默認值爲PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 5
parallel_adaptive_multi_user=true|false
Oracle 10g R2下,並行執行默認是啓用的。這個參數的默認值爲true,它讓Oracle根據SQL執行時系統的負載狀況,動態地調整SQL的並行度,以取得最好的SQL執行性能。算法
PARALLEL_DEGREE_POLICY
PARALLEL_DEGREE_POLICY specifies whether or not automatic degree of Parallelism, statement queuing, and in-memory parallel execution will be enabled.Values:sql
Note: If the table parallel degree has been set as "default", sql would compute its own DOP regardless parallel_degree_policy is MANUAL or LIMITED. When parallel_degree_policy=AUTO, it would trigger automatically parallel degree .
parallel_min_percent
這個參數指定並行執行時,申請並行服務進程的最小值,它是一個百分比,好比咱們設定這個值爲50. 當一個SQL須要申請20個並行進程時,若是當前並行服務進程不足,按照這個參數的要求,這個SQL好比申請到20*50%=10個並行服務進程,若是不可以申請到這個數量的並行服務,SQL將報出一個ORA-12827的錯誤。 當這個值設爲Null時,表示全部的SQL在作並行執行時,至少要得到兩個並行服務進程。
Note:當parallel_degree_policy=AUTO時,若是沒有得到申請的進程,則該並行sql則會進入隊列數據庫
PARALLEL_FORCE_LOCAL
This parameter specifies whether a SQL statement executed in parallel is restricted to a single instance in an Oracle RAC environment. By setting this parameter to TRUE, you restrict the scope of the parallel server processed to the single Oracle RAC instance where the query coordinator is running.
The recommended value for the PARALLEL_FORCE_LOCAL parameter is FALSE.
PARALLEL_DEGREE_POLICY
該參數爲11g的新增參數,有以下3個屬性值:
manual,默認值,表示不自動調節並行度。
auto,自動調節並行度。
limited,對於在相關表或者索引上已經定義了並行度的查詢進行自動並行度調節,沒有在相關表或者索引上已經定義並行度的查詢不進行自動並行度調節。
PARALLEL_THREADS_PER_ CPU
一個CPU 在並行執行過程當中可處理的進程或線程的數量,並優化並行自適應算法和負載均衡算法。若是計算機在執行一個典型查詢時有超負荷的跡象,應減少該數值爲任何非零值。 根據操做系統而定 (一般爲 2)
parallel_automatic_tuning
若是設置爲 TRUE,Oracle 將爲控制並行執行的參數肯定默認值。除了設置該參數外,你還必須爲系統中的表設置並行性。以在10g中廢棄,只爲向下兼容保留。緩存
PARALLEL_MIN_TIME_THRESHOLD
This parameter specifies the minimum execution time a statement should have before the statement is considered for automatic degree of parallelism. By default, this is set to 10 seconds. Automatic degree of parallelism is only enabled if PARALLEL_DEGREE_POLICY is set to AUTO or LIMITED. The syntax is:
PARALLEL_MIN_TIME_THRESHOLD = { AUTO | integer }
The default is AUTO.
PARALLEL_SERVERS_TARGET
This parameter specifies the number of parallel server processes allowed to run parallel statements before statement queuing is used. The default value is:
PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 2
In the formula, the value assigned to concurrent_parallel_users running at the default degree of parallelism on an instance is dependent on the memory management setting. If automatic memory management is disabled (manual mode), then the value of concurrent_parallel_users is 1. If PGA automatic memory management is enabled, then the value of concurrent_parallel_users is 2. If global memory management or SGA memory target is used in addition to PGA automatic memory management, then the value of concurrent_parallel_users is 4.
When PARALLEL_DEGREE_POLICY is set to AUTO, statements that require parallel execution are queued if the number of parallel processes currently in use on the system equals or is greater than PARALLEL_SERVERS_TARGET. This is not the maximum number of parallel server processes allowed on a system (that is controlled by PARALLEL_MAX_SERVERS). However, PARALLEL_SERVERS_TARGET and parallel statement queuing is used to ensure that each statement that requires parallel execution is allocated the necessary parallel server resources and the system is not flooded with too many parallel server processes.
parallel_execution_message_size
指定並行執行 (並行查詢、PDML、並行恢復和複製) 消息的大小。若是值大於 2048 或 4096,就須要更大的共享池。若是 PARALLEL_AUTOMATIC_TUNING =TRUE,將在大存儲池以外指定消息緩衝區。 若是PARALLEL_AUTOMATIC_TUNING 爲 FALSE,一般值爲 2148;若是PARALLEL_AUTOMATIC_TUNING 爲 TRUE ,則值爲 4096 (根據操做系統而定)。性能優化
PARALLEL_DEGREE_LIMIT
With automatic degree of parallelism, Oracle automatically decides whether or not a statement should execute in parallel and what degree of parallelism the statement should use. The optimizer automatically determines the degree of parallelism for a statement based on the resource requirements of the statement. However, the optimizer will limit the degree of parallelism used to ensure parallel server processes do not flood the system. This limit is enforced by PARALLEL_DEGREE_LIMIT
Values:服務器
並行度能夠經過如下三種方式來設定:
一、使用Hint 指定並行度。
二、使用alter session force parallel 設定並行度。
三、使用SQL中引用的表或者索引上設定的並行度,原則上Oracle 使用這些對象中並行度最高的那個值做爲當前執行的並行度。
示例:
SQL>Select /*+parallel(t 4) */ count(*) from t;
SQL>Alter table t parallel 4;
SQL>Alter session force parallel query parallel 4;
SQL>alter session force parallel query;
Oracle 默認並行度計算方式:
一、Oracle 根據CPU的個數,RAC實例的個數以及參數parallel_threads_per_cpu的值,計算出一個並行度。
二、對於並行訪問分區操做,取須要訪問的分區數爲並行度。
並行度的優先級別從高到低:
Hint->alter session force parallel->表,索引上的設定-> 系統參數
實際上,並行只有才系統資源比較充足的狀況下,纔會取得很好的性能,若是系統負擔很重,不恰當的設置並行,反而會使性能大幅降低。
如何啓用並行session
能夠用hint、alter session或者設置對象並行屬性三種方式設置啓用並行。三種方式任意一種就可使並行生效,若是多種方式同時存在的話,則優先級順序是:hint -> alter session -> table/index degree。併發
alter session force query parallel 8;oracle
alter session enable parallel dml;
alter session force parallel dml parallel 8;
alter session force parallel ddl parallel 8;
注意:上述的alter session enable只是表示讓當前會話支持並行,最終並行須要經過hint或者table/index degree來實現;而alter session force表示強制並行,無需hint等配合使用。
11g中的並行
在Oracle 11g R2以及以前的版本,你的SQL執行可能被延遲,直到有充足的並行服務器可用。
Oracle有一種輪換IO機制,叫作「直接路徑IO」,若是它判斷到繞過緩存區直接執行IO會更快速的話, 它就會啓用。例如,Oracle在讀寫臨時段進行排序或者整理中間結果集時就會使用直接IO。從Oracle 11g開始,Oracle有時也優先利用直接路徑IO來處理串行表訪問,而不是正常的緩存IO。
在執行並行查詢操做時,Oracle一般會使用直接路徑IO。經過使用直接路徑IO,Oracle能夠避免建立高速緩存競爭,並可使IO更加優化地在並行進程之間分配。此外,對於執行全表掃描的並行操做,在高速緩存找到匹配數據的機會至關低,所以高速緩存幾乎沒有增長什麼價值。
在Oracle 10g以及更早的版本,並行查詢老是使用直接路徑IO,而串行查詢將老是使用緩存IO。在11g中,Oracle能夠對並行查詢利用緩存IO(從11g R2之後的版本支持),並且串行查詢也可能利用直接路徑IO。然而,並行查詢仍然不太可能利用緩存IO,所以,可能比串行查詢須要更高的IO成本。固然, 更高的IO成本將在全部並行進程之間共享,這樣總體性能仍可能更勝一籌。
並行的優化準則
從優化串行執行的SQL開始
一個最理想的並行計劃與最佳的串行計劃多是有區別的。例如,並行處理一般從表或索引的掃描開始,而最佳串行計劃多是基於索引查找開始。然而,你應該確保你的查詢在進行並行優化以前先對串行執行進行優化,緣由以下:
一、串行調試的結構和方法主要針對索引和統計集合,而這些常常對好的並行調試也很是關鍵。
二、若是請求並行執行的資源不可用,你的查詢可能被串行化(這取決於「PARALLEL_DEGREE_ POLICY」和「PARALLEL_MIN_PERCENT」的設置)。在這種狀況下,你要確保你並行查詢的串行計劃足夠好。
缺乏調優的SQL甚至可能變成更差的SQL,至少考慮到對其餘用戶的影響時是這樣,這使它被容許消耗數據庫服務器更多的CPU和IO資源。
在爲並行執行優化SQL語句時,要從未串行執行SQL優化開始。
確保該SQL是合適的並行執行SQL
不是每一個SQL都能從並行執行中獲益的。下面是一些例子,這些狀況的SQL語句可能不該該被並行化。
一、串行執行時,執行時間很短的SQL語句。
二、可能在多個會話中高併發率運行的SQL語句。
三、基於索引查找的SQL語句。非並行的索引查找或者範圍掃描不能被並行化。然而,索引全掃描能夠被並行化。在分區索引上的索引查找也能夠被並行化。
綜上3點,OLTP類型的查詢一般不適合並行化處理。
確保系統適合配置爲並行執行
不是全部的SQL都適合並行執行,也不是全部的數據庫服務器主機適合配置並行處理。在當今世界,大部分物理服務器主機都知足以下最小需求:多塊CPU和 跨多個物理驅動器的數據帶。然而,一些虛擬主機可能不知足這些最小需求,而桌面計算機一般只有惟一的磁盤設備,所以一般不適合調整爲並行執行。
不要嘗試在那些不知足最小需求(多塊CPU和跨多個磁盤驅動器的數據帶)的計算機系統上使用並行執行。
確保執行計劃的全部部分都被並行化了
在複雜的並行SQL語句中,很重要的一點是要確保該查詢執行的全部重要步驟都實現了並行。若是某複雜查詢的其中一個步驟是串行執行的,其餘並行步驟可能 也不得不等待該串行步驟完成,這樣並行機制的優點就徹底喪失了。「PLAN_TABLE」表中的「OTHER_TAG」列用 「PARALLEL_FROM_SERIAL」標記指定了這樣一個步驟,「DBMS_XPLAN」在「IN-OUT」列中記錄了「S->P」。例如:在下面的例子中表「T1」是並行化的,可是表「T」不是。對兩個表的鏈接和「GROUP BY」包括許多並行操做,可是對「T」表的全表掃描不是並行化的,串到並(S->P)標記展現了「t」行被串行提取到後續並行操做中:
SQL> ALTER TABLE customers PARALLEL(DEGREE 4);
SQL> ALTER TABLE sales NOPARALLEL ;
SQL> explain plan for select /*+ ordered use_hash(t1) */ t.name,sum(t.id) from t,t1 where t.id=t1.object_id group by t.name;
SQL> 1* select * from table(dbms_xplan.display)
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2575143521
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 61 | 4758 | 22 (10)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 61 | 4758 | 22 (10)| 00:00:01 | Q1,02 | P->S | QC (RAND) |
| 3 | HASH GROUP BY | | 61 | 4758 | 22 (10)| 00:00:01 | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 61 | 4758 | 22 (10)| 00:00:01 | Q1,02 | PCWP | |
| 5 | PX SEND HASH | :TQ10001 | 61 | 4758 | 22 (10)| 00:00:01 | Q1,01 | P->P | HASH |
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 6 | HASH GROUP BY | | 61 | 4758 | 22 (10)| 00:00:01 | Q1,01 | PCWP | |
|* 7 | HASH JOIN | | 61 | 4758 | 21 (5)| 00:00:01 | Q1,01 | PCWP | |
| 8 | BUFFER SORT | | | | | | Q1,01 | PCWC | |
| 9 | PX RECEIVE | | 61 | 3965 | 12 (0)| 00:00:01 | Q1,01 | PCWP | |
| 10 | PX SEND BROADCAST | :TQ10000 | 61 | 3965 | 12 (0)| 00:00:01 | | S->P | BROADCAST |
| 11 | TABLE ACCESS FULL | T | 61 | 3965 | 12 (0)| 00:00:01 | | | |
| 12 | PX BLOCK ITERATOR | | 52078 | 661K| 8 (0)| 00:00:01 | Q1,01 | PCWC | |
| 13 | INDEX FAST FULL SCAN| T1_IDX | 52078 | 661K| 8 (0)| 00:00:01 | Q1,01 | PCWP | |
----------------------------------------------------------------------------------------------------------------------
像前面這種狀況,部分並行化執行計劃可能會致使兩方面效果都不好:消耗的時間並無改善,由於串行操做造成了整個執行的瓶頸。然而,該SQL還捆綁了並行服務器進程,並且可能影響其餘併發執行SQL的性能。
若是咱們爲表「t」設置一個默認的並行度,該串行瓶頸將會消失。對「t」表的全掃描如今是按並行執行了,並且「串到並S->P」瓶頸將被全並行的「併到並P->P」操做替代
在優化並行執行計劃時,要確保全部相關步驟都在並行執行:「DBMS_XPLAN」中的串到並S->P 標記或者「PLAN_TABLE」中的「PARALLEL_FROM_SERIAL」一般指示在並行計劃的某些方面存在串行瓶頸。
Monitor parallel execution
SQL> select * from v$pq_sesstat;
STATISTIC LAST_QUERY SESSION_TOTAL
------------------------------ ---------- -------------
Queries Parallelized 1 13
DML Parallelized 0 0
DDL Parallelized 0 0
DFO Trees 1 13
Server Threads 6 0
Allocation Height 3 0
Allocation Width 1 0
Local Msgs Sent 362 303740
Distr Msgs Sent 0 0
Local Msgs Recv'd 368 303782
Distr Msgs Recv'd 0 0
11 rows selected.
SQL> select DFO_NUMBER, TQ_ID, SERVER_TYPE, NUM_ROWS ,BYTES,process from v$pq_tqstat order by dfo_number , tq_id , server_type;
DFO_NUMBER TQ_ID SERVER_TYPE NUM_ROWS BYTES PROCESS
---------- ---------- --------------- ---------- ---------- --------
1 0 Consumer 17151 100454 P001
1 0 Consumer 17242 100969 P002
1 0 Consumer 17257 101058 P000
1 0 Producer 1971 9955 P004
1 0 Producer 29565 174989 P005
1 0 Producer 20114 117537 P003
1 1 Consumer 893 8107 P002
1 1 Consumer 2914 26341 P001
1 1 Consumer 0 60 P000
1 1 Producer 611 5494 P003
1 1 Producer 2593 23493 P005
1 1 Producer 603 5521 P004
1 2 Consumer 3807 19040 QC
1 2 Producer 2914 14545 P001
1 2 Producer 893 4475 P002
1 2 Producer 0 20 P000
16 rows selected.
Obviously, from the v$pq_tqstat, the DOP is downgrade to 3, and have two slave sets. From the v$tq_sesstat, we can see that what’s the process. How these processes cooperated together to generated the result. In this sample, P003, P004,P005 generate the data and feed to P000,P001,P002, totally twice. Then P000,P001,P002 feed the data to QC, the query coordinator. Also, we can find that P000 at the first time received 17257 rows, but at the second time it received 0 rows, and lastly, it product 0 rows to QC. Why?
Let’s look at the execution plan for further investigation.
SQL> @utlxplp
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1177066807
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3867 | 147K| 13 (8)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 3867 | 147K| 13 (8)| 00:00:01 | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | 3867 | 147K| 13 (8)| 00:00:01 | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 53332 | 677K| 7 (0)| 00:00:01 | Q1,02 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | 53332 | 677K| 7 (0)| 00:00:01 | Q1,00 | P->P | HASH |
| 6 | PX BLOCK ITERATOR | | 53332 | 677K| 7 (0)| 00:00:01 | Q1,00 | PCWC | |
| 7 | TABLE ACCESS FULL| PRODUCTS | 53332 | 677K| 7 (0)| 00:00:01 | Q1,00 | PCWP | |
| 8 | PX RECEIVE | | 3867 | 98K| 5 (0)| 00:00:01 | Q1,02 | PCWP | |
| 9 | PX SEND HASH | :TQ10001 | 3867 | 98K| 5 (0)| 00:00:01 | Q1,01 | P->P | HASH |
| 10 | PX BLOCK ITERATOR | | 3867 | 98K| 5 (0)| 00:00:01 | Q1,01 | PCWC | |
| 11 | TABLE ACCESS FULL| COSTS | 3867 | 98K| 5 (0)| 00:00:01 | Q1,01 | PCWP | |
-----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("C"."PROD_ID"="P"."PROD_ID")
This is a hash-hash parallel distribute, using hash joining. firstly, Slave set(Q1,00) scan products table and send the results to slave set(Q1,02), and slave set(Q1,01) scan the costs table and send results to slave set(Q1,02), which slave in slave set(Q1,02) to send to is dependent on the hash value of join key. as the table costs only have two distinct values for prod_id, so the rows in costs only have two target slave to send to, resulting one slave of the slave set (Q1,02) receive 0 rows. After the slaves in (Q1,02) received rows from the other two slave sets, they hash join the rows and send the result to QC, obviously, one slave will have no rows to process.
This is why 0 rows in the above output.
Also, you can enable the trace for parallel execution, through this way:
alter session set events '10132 trace name context forever';
Compute the variance of bytes grouped by TQ_ID. Large variances indicate workload imbalances. You should investigate large variances to determine whether the producers start out with unequal distributions of data, or whether the distribution itself is skewed. If the data itself is skewed, this might indicate a low cardinality, or low number of distinct values.
Some Common Sense
BTW, introduce two useful link about parallel execution.
Oracle Database Parallel Execution Fundamental
http://www.oracle.com/technetwork/articles/datawarehouse/twp-parallel-execution-fundamentals-133639.pdf
How Parallel Execution Works
http://docs.oracle.com/cd/E11882_01/server.112/e25523/parallel002.htm#VLDBG0101
參考至:《讓Oracle跑得更快》譚懷遠著
《讓Oracle跑得更快2》譚懷遠著
http://howe.im/%E6%95%B0%E6%8D%AE%E5%BA%93/137.html
http://www.cnblogs.com/daduxiong/archive/2010/08/24/1807427.html
http://www.searchdatabase.com.cn/showcontent_44070.htm
http://xuguohao.gotoip55.com/?p=142
http://blog.csdn.net/tianlesoftware/article/details/5854583
http://docs.oracle.com/cd/E11882_01/server.112/e17110/initparams176.htm
http://space.itpub.net/17203031/viewspace-696389
http://os2ora.com/monitor-parallel-execution/
http://oracledoug.com/px.pdf
http://docs.oracle.com/cd/E11882_01/server.112/e25523/parallel006.htm#VLDBG1513
http://www.oracle.com/technetwork/articles/datawarehouse/twp-parallel-execution-fundamentals-133639.pdf http://docs.oracle.com/cd/E11882_01/server.112/e25523/parallel005.htm#CIHHGECI http://docs.oracle.com/cd/E11882_01/server.112/e40402/initparams181.htm#REFRN10310 http://www.cnblogs.com/luoyx/archive/2011/12/26/2302587.html本文原創,轉載請註明出處、做者若有錯誤,歡迎指正郵箱:czmcj@163.com