【原創】Oracle 並行原理與示例總結

leonarding發表於2013-01-25

《Oracle 並行原理與示例總結》

並行:把一個工作分成幾份,分給不同程式同時進行處理。 程式層面

併發:多個會話同時進行訪問,就是通常所說併發數。會話層面

資料庫版本

LEO1@LEO1> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

PL/SQL Release 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production


給出一個2表關聯的並行查詢執行計劃,並畫出並行資料流圖

1)並行應用場合:

1.OLAP 業務模式

首先說明一個我們經常混洗的概念OLAP和資料倉儲是不是一個東西。

回答:NO

OLAP是一種業務模式,是一種批次載入批次檢索的業務模式,例如 線上資料分析系統。

資料倉儲:是支撐這種業務模式的底層資料庫。

2.系統資源相對空閒

當系統的CPU較多   IO負載不高   記憶體夠大的時候,可以使用並行操作,需要考慮資源平衡。

3.資料符合並行特點

這個說明是什麼呢,就是你所操作的資料沒有序列化,可以拆分,同時對不同部分資料進行操作,

如果是那種只有計算出前者才能統計後者的流程就不適合使用並行操作了。

例如統計行數就可以使用並行,讓10個程式分別統計不同區域的行數最後把結果合併起來返回給使用者。

2)首先明示一下使用並行的3種方法
1.hints     方式 臨時有效

select /*+ parallel(leo1 2) */ count(*) from leo1;

2.alter table 物件級別定義並行 直接修改物件屬性 長期有效

alter table leo1 parallel 4;       定義leo1表並行度為4

3.alter session force parallel      會話級別定義並行 會話生命期中有效

alter session force parallel query parallel 4;       強制定義並行度為4

通常/*+ parallel(leo1 4) */

4.並行查詢和並行DDL可以無障礙使用並行,如果想使用並行DML,就需要啟動會話DML並行功能

alter session enable parallel dml;

3)實驗

現在我們做一個並行操作,分析一下並行執行計劃流程,感性的感受一下並行的魅力

LEO1@LEO1> drop table leo1 purge;      清理環境

Table dropped.

LEO1@LEO1> drop table leo2 purge;

Table dropped.

LEO1@LEO1> create table leo1 as select * from dba_objects;      建立leo1

Table created.

LEO1@LEO1> create table leo2 as select * from leo1;      模擬leo1建立leo2

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO1',

method_opt=>'for all indexed columns size 254');

PL/SQL procedure successfully completed.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO2',

method_opt=>'for all indexed columns size 254');

PL/SQL procedure successfully completed.

leo1leo2進行全表整體分析包括資料分佈情況分析(資料傾斜程度,即直方圖)

Tips

如果想讓n個表關聯查詢並且都啟並行的話,hints如何寫呢,請看下面

/*+ parallel(leo1,leo2,2) */ 對嗎? 當然不對

/*+ parallel(leo1 leo2,2) */ 對嗎? 當然也不對

/*+ parallel(leo1,2) parallel(leo2,2) */  對嗎?  Yes  親們要看好哦

/*+ parallel(leo1,2) parallel(leo2,2) parallel(leo3,2) ……*/   後面同理延續

LEO1@LEO1> select /*+ parallel(leo1,2) parallel(leo2,2) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

Execution Plan      並行度為2 執行計劃

----------------------------------------------------------

Plan hash value: 2718975204

-------------------------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |          |     1 |    26 |   320   (1)| 00:00:04 |        |      |            |

|   1 |  SORT AGGREGATE           |          |     1 |    26 |            |          |        |      |            |

|   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)    | :TQ10001 |     1 |    26 |            |          |  Q1,01 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE        |          |     1 |    26 |            |          |  Q1,01 | PCWP |            |

|*  5 |      HASH JOIN            |          | 72017 |  1828K|   320   (1)| 00:00:04 |  Q1,01 | PCWP |            |

|   6 |       PX BLOCK ITERATOR   |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWC |            |

|   7 |        TABLE ACCESS FULL  | LEO1     | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWP |            |

|   8 |       PX RECEIVE          |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWP |            |

|   9 |        PX SEND BROADCAST  | :TQ10000 | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | P->P | BROADCAST  |

|  10 |         PX BLOCK ITERATOR |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | PCWC |            |

|  11 |          TABLE ACCESS FULL| LEO2     | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | PCWP |            |

-------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   5 - access("LEO1"."OBJECT_ID"="LEO2"."OBJECT_ID")

解釋一下並行執行計劃步驟,並行執行計劃應該從下往上讀,當看見PXparallel execution)關鍵字說明使用了並行技術

1. |   7 | TABLE ACCESS FULL  | LEO1     |   首先對leo1表進行全表掃描

2. |   6 |  PX BLOCK ITERATOR   | 並行程式以迭代iterator的方式分割資料塊

3. |  11 |   TABLE ACCESS FULL| LEO2 | 然後對leo2表進行全表掃描

4. |  10 |    PX BLOCK ITERATOR |並行程式以迭代iterator的方式分割資料塊

5. |   9 |     PX SEND BROADCAST  | :TQ10000 |並行程式以廣播方式傳送掃描結果

6. |   8 |      PX RECEIVE    |並行程式接收傳送過來的結果

7. |*  5 |       HASH JOIN |在這裡把leo1 leo2表掃描結果做雜湊關聯

8. |   4 |        SORT AGGREGATE|將雜湊關聯結果做count統計操作

9. |   3 |         PX SEND QC (RANDOM)| :TQ10001 |按照隨機順序傳送給並行協調程式QCquery coordinator)整合結果

10. |   2 |         PX COORDINATOR |接收資料

11. |   1 |          SORT AGGREGATE |整合結果      

12. |   0 |           SELECT STATEMENT |完畢後QC將最終結果返回給使用者

說明並行執行計劃中特有的IN-OUT列的含義(指明瞭操作中資料流的方向)               
Parallel to Serial
P->S: 表示一個並行操作向一個序列操作傳送資料,通常是將並行結果傳送給並行

排程程式QC進行彙總  例如  PX SEND QC (RANDOM)

Serial to ParallelS->P: 表示一個序列操作向一個並行操作傳送資料,如果select部分是序列操作,就會出現這個情況

Parallel to ParallelP->P):表示一個並行操作向另一個並行操作傳送資料,一般是並行父程式與並行子程式之間的資料交流

Parallel Combined with parent(PCWP): 資料在同一組的並行程式之間傳遞
Parallel Combined with Child(PCWC): 資料在不同組的並行程式之間傳遞

下面我們從v$pq_tqstat動態效能檢視中檢視一下並行程式的工作量平衡情況

LEO1@LEO1> select dfo_number,tq_id,server_type,num_rows,bytes,process from v$pq_tqstat;

DFO_NUMBER      TQ_ID  SERVER_TYPE    NUM_ROWS  BYTES  PROCESS

---------- ---------- -------------------- ---------- ---------- ----------------------------------------------------------

         1          0    Consumer       72017     422219   P000

         1          1    Producer            1         36   P000

         1          0    Consumer       72017     422219   P001

         1          1    Producer            1         36   P001

PROCESSP000  P001  2個程式號,說明我們啟動了2個並行程式和我們設定的並行度一致

SERVER_TYPE:程式在處理中扮演的角色

Producer  扮演並行服務角色,幹活的(具體處理操作)

              Consumer 扮演並行協調角色,分配任務和結果合併

NUM_ROWS:上面角色處理的行數

BYTES:行數所佔的空間位元組

TQ_IDtable queue ID 區分同一個程式扮演2個角色時的不同操作(來自官方文件)和執行計劃中TQ同理

DFO_NUMBER1 = 第一次並行操作   2 = 第二次並行操作   3 = 第三次並行操作

              第一次並行操作牽涉到兩個並行程式 P000  P001

              DFO data flow operator)操作流程

Tips

LEO1@LEO1> select distinct sid from v$mystat;

       SID

------------------

       133

LEO1@LEO1> select sid,PDML_STATUS,PDDL_STATUS,PQ_STATUS from v$session;

SID  PDML_STA   PDDL_STA   PQ_STATU

---------- -------- -------- ---------------- -------- ----

133  DISABLED   ENABLED    ENABLED

我們可以利用v$session中的PDML_STATUS,PDDL_STATUS,PQ_STATUS檢視當前會話的預設並行狀態

就自己本機的硬體情況,透過SQL示例,來找到最優的並行度

1)並行度:就是oracle在進行並行處理時,會啟動幾個並行服務程式來同時處理資料,注意看看資料需要幾步處理,每一步都啟n個程式而不是隻啟n個程式

     並行度設定:一般來講一個CPU核心可以支撐一個並行度,一臺多核伺服器中通常採用CPU核數50%來設定並行度,餘下的CPU處理其他程式

     並行度與硬體關係密切,同樣並行度在不同硬體上體現的效果是截然不同的

     並行度與併發數關係:總並行數=並行度*併發數,當並行度確立後,併發數越多總並行數越高

2)實驗

我使用的是meACER小本本,例舉一下配置

英特爾@酷睿 i3-370M   雙核四執行緒

14LED螢幕

NVIDIA GeForce@GT 520M

4G DDR3

500GB

DVD-SuperMulti燒錄

Acer Nplify 802.11b/g/n

6芯鋰離子電池

為了對比方便,我還是使用剛才SQL語句只是變化不同的並行度,來對比執行計劃找到最優的並行度

並行度設定成2

LEO1@LEO1> select /*+ parallel(leo1,2) parallel(leo2,2) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

Execution Plan

----------------------------------------------------------

Plan hash value: 2718975204

-------------------------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT          |          |     1 |    26 |   320   (1)| 00:00:04 |        |      |            |

|   1 |  SORT AGGREGATE           |          |     1 |    26 |            |          |        |      |            |

|   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)    | :TQ10001 |     1 |    26 |            |          |  Q1,01 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE        |          |     1 |    26 |            |          |  Q1,01 | PCWP |            |

|*  5 |      HASH JOIN            |          | 72017 |  1828K|   320   (1)| 00:00:04 |  Q1,01 | PCWP |            |

|   6 |       PX BLOCK ITERATOR   |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWC |            |

|   7 |        TABLE ACCESS FULL  | LEO1     | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWP |            |

|   8 |       PX RECEIVE          |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,01 | PCWP |            |

|   9 |        PX SEND BROADCAST  | :TQ10000 | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | P->P | BROADCAST  |

|  10 |         PX BLOCK ITERATOR |          | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | PCWC |            |

|  11 |          TABLE ACCESS FULL| LEO2     | 72017 |   914K|   160   (1)| 00:00:02 |  Q1,00 | PCWP |            |

-------------------------------------------------------------------------------------------------------------------

效能指標Cost=160   Time=00:00:02

並行度設定成4

LEO1@LEO1> select /*+ parallel(leo1,4) parallel(leo2,4) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

Execution Plan

----------------------------------------------------------

Plan hash value: 589148148

-------------------------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT          |          |     1 |    26 |   160   (1)| 00:00:02 |        |      |            |

|   1 |  SORT AGGREGATE           |          |     1 |    26 |            |          |        |      |            |

|   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    26 |            |          |  Q1,02 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE        |          |     1 |    26 |            |          |  Q1,02 | PCWP |            |

|*  5 |      HASH JOIN            |          | 72017 |  1828K|   160   (1)| 00:00:02 |  Q1,02 | PCWP |            |

|   6 |       PX RECEIVE          |          | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|   7 |        PX SEND HASH       | :TQ10000 | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |

|   8 |         PX BLOCK ITERATOR |          | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,00 | PCWC |            |

|   9 |          TABLE ACCESS FULL| LEO1     | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|  10 |       PX RECEIVE          |          | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|  11 |        PX SEND HASH       | :TQ10001 | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |

|  12 |         PX BLOCK ITERATOR |          | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,01 | PCWC |            |

|  13 |          TABLE ACCESS FULL| LEO2     | 72017 |   914K|    80   (0)| 00:00:01 |  Q1,01 | PCWP |            |

-------------------------------------------------------------------------------------------------------------------

效能指標Cost=80   Time=00:00:01

LEO1@LEO1> select dfo_number,tq_id,server_type,num_rows,bytes,process from v$pq_tqstat;

DFO_NUMBER      TQ_ID  SERVER_TYPE    NUM_ROWS  BYTES  PROCESS

---------- ---------- -------------------- ---------- ---------- ----------------------------------------------------------

         1          0    Consumer       72017     422219   P000

         1          1    Producer            1         36   P000

         1          0    Consumer       72017     422219   P001

         1          1    Producer            1         36   P001

         1          0    Producer        71650     418494   P002

         1          0    Producer        72384     425944   P003

         1          1    Consumer           2         72   QC

PROCESSP000  P001  P002   P003  說明我們啟動了4個並行程式

CostTime指標而言42個並行度效率要高一倍

並行度設定成8

LEO1@LEO1> select /*+ parallel(leo1,8) parallel(leo2,8) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

Execution Plan

----------------------------------------------------------

Plan hash value: 589148148

-------------------------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT          |          |     1 |    26 |    80   (0)| 00:00:01 |        |      |            |

|   1 |  SORT AGGREGATE           |          |     1 |    26 |            |          |        |      |            |

|   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    26 |            |          |  Q1,02 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE        |          |     1 |    26 |            |          |  Q1,02 | PCWP |            |

|*  5 |      HASH JOIN            |          | 72017 |  1828K|    80   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|   6 |       PX RECEIVE          |          | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|   7 |        PX SEND HASH       | :TQ10000 | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |

|   8 |         PX BLOCK ITERATOR |          | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,00 | PCWC |            |

|   9 |          TABLE ACCESS FULL| LEO1     | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|  10 |       PX RECEIVE          |          | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|  11 |        PX SEND HASH       | :TQ10001 | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |

|  12 |         PX BLOCK ITERATOR |          | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,01 | PCWC |            |

|  13 |          TABLE ACCESS FULL| LEO2     | 72017 |   914K|    40   (0)| 00:00:01 |  Q1,01 | PCWP |            |

-------------------------------------------------------------------------------------------------------------------效能指標Cost=53

效能指標Cost=40  代價又減少了一半

並行度設定成16

LEO1@LEO1> select /*+ parallel(leo1,16) parallel(leo2,16) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

Execution Plan

----------------------------------------------------------

Plan hash value: 589148148

-------------------------------------------------------------------------------------------------------------------

| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT          |          |     1 |    26 |    40   (0)| 00:00:01 |        |      |            |

|   1 |  SORT AGGREGATE           |          |     1 |    26 |            |          |        |      |            |

|   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    26 |            |          |  Q1,02 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE        |          |     1 |    26 |            |          |  Q1,02 | PCWP |            |

|*  5 |      HASH JOIN            |          | 72017 |  1828K|    40   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|   6 |       PX RECEIVE          |          | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|   7 |        PX SEND HASH       | :TQ10000 | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |

|   8 |         PX BLOCK ITERATOR |          | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,00 | PCWC |            |

|   9 |          TABLE ACCESS FULL| LEO1     | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|  10 |       PX RECEIVE          |          | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,02 | PCWP |            |

|  11 |        PX SEND HASH       | :TQ10001 | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |

|  12 |         PX BLOCK ITERATOR |          | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,01 | PCWC |            |

|  13 |          TABLE ACCESS FULL| LEO2     | 72017 |   914K|    20   (0)| 00:00:01 |  Q1,01 | PCWP |            |

-------------------------------------------------------------------------------------------------------------------

效能指標Cost=20  代價又減少了一半

並行度設定成32

LEO1@LEO1> select /*+ parallel(leo1,32) parallel(leo2,32) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

效能指標Cost=10  代價又減少了一半

並行度設定成64

LEO1@LEO1> select /*+ parallel(leo1,64) parallel(leo2,64) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

效能指標Cost=5  代價又減少了一半

並行度設定成128

LEO1@LEO1> select /*+ parallel(leo1,128) parallel(leo2,128) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

效能指標Cost=2  代價又減少了一半

並行度設定成256

LEO1@LEO1> select /*+ parallel(leo1,128) parallel(leo2,128) */ count(*) from leo1,leo2

where leo1.object_id=leo2.object_id;

效能指標Cost=2  好一致了

小結:當並行度設定成256Cost不在減少了,說明此時並行度最優。說明一下我的這張表只有7w多條資料,有可能資料量比較少CPU可以很快的執行完畢,所以Cost也比較小。


針對PARALLEL_DEGREE_POLICY的三個值,分別演示它們的效果

1)自動並行度策略PARALLEL_DEGREE_POLICYORACLE 11G新特性,透過它可以設定並行度策略

這個引數有三個值:manual        手動方式,也是預設方式,oracle不會擅自調整並行度

                                    limited         限制方式

                                    auto           自動方式

2)實驗

LEO1@LEO1> drop table leo3 purge;    清理環境

Table dropped.

LEO1@LEO1> drop table leo4 purge;

Table dropped.

LEO1@LEO1> create table leo3 as select * from dba_objects;    建立leo3

Table created.

LEO1@LEO1> create table leo4 as select * from dba_objects;    建立leo4

Table created.

parallel_degree_policy=manual

如果我們設定manualoracle不會參與調整並行度,不管資源負載如何,並行度是多少就用多少

第一種設定方式

LEO1@LEO1> alter table leo3 parallel 4;    直接指定leo3表並行度為4

Table altered.

物件級別定義並行,直接修改物件屬性,長期有效

LEO1@LEO1> select table_name,degree from user_tables where table_name in ('LEO3');   並行度已經調整完畢

TABLE_NAME                     DEGREE

------------------------------ -------------------------------

LEO3                            4

第二種設定方式

LEO1@LEO1> alter table leo3 parallel(degree 4);            這種方法和上面方法同理

第一種設定方式

LEO1@LEO1> alter table leo4 parallel;                設定leo4表的並行度為default

Table altered.

第二種設定方式

LEO1@LEO1> alter table leo4 parallel(degree default);   同理也是設定為default

Table altered.

第三種設定方式  hint

select /*+ parallel */ * from leo4;          不寫並行度就是使用oracle預設並行度(臨時有效)

這三種方式我們選擇其一即可

LEO1@LEO1> select table_name,degree from user_tables where table_name in ('LEO3','LEO4');

TABLE_NAME                     DEGREE

------------------------------ -------------------- --------------------

LEO3                            4

LEO4                            DEFAULT      預設並行度

設定自動並行度為manual

LEO1@LEO1> alter session set parallel_degree_policy=manual;

Session altered.

LEO1@LEO1> select count(*) from leo3;       統計leo3表使用並行操作

  COUNT(*)

------------------

     72017

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';  

STATISTIC                      LAST_QUERY    SESSION_TOTAL

------------------------------ ---------- ------------------------------ ---------- ----

Allocation Height                4               0

使用並行度是4oracle沒有改變並行度

LEO1@LEO1> select count(*) from leo4;    這張表是使用oracle預設並行度

  COUNT(*)

----------

     72018

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';

STATISTIC                      LAST_QUERY SESSION_TOTAL

------------------------------ ---------- -------------

Allocation Height                       4             0

並行度是4oracle還是使用預設並行度

parallel_degree_policy=limited

如果我們設定limited

當有直接指定並行度時繼續使用

當表是使用oracle預設並行度時,oracle會根據資源負載自動評估調整並行度

LEO1@LEO1> alter table leo3 parallel(degree 6);   我把leo3表並行度調整為6

Table altered.

LEO1@LEO1> alter table leo4 parallel(degree default);   leo4還是使用oracle預設並行度

Table altered.

LEO1@LEO1> select table_name,degree from user_tables where table_name in ('LEO3','LEO4');

TABLE_NAME   DEGREE       進行檢查

---------- --------------------

LEO3                6

LEO4          DEFAULT

設定自動並行度為limited

LEO1@LEO1> alter session set parallel_degree_policy=limited;   

Session altered.

LEO1@LEO1> select count(*) from leo3;       統計leo3表使用並行操作

  COUNT(*)

----------

     72017

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';

STATISTIC                      LAST_QUERY  SESSION_TOTAL

------------------------------ ---------- ------------------------ ---------- ---------

Allocation Height                       6             0

使用並行度是6oracle沒有改變並行度

LEO1@LEO1> select count(*) from leo4;       使用oracle預設並行度

  COUNT(*)

----------------

     72018

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';

STATISTIC                      LAST_QUERY   SESSION_TOTAL

------------------------------ ---------- ------------------ ---------- -------------

Allocation Height                       0             0

這回oracle改變了並行度=0,因為oracle覺得不使用並行也能有很好的效果

parallel_degree_policy=auto

如果我們設定auto,不論是直接指定的並行度還是使用oracle預設並行度,oracle都會進行干預調整,oracle會根據資源負載情況來動態調整並行度。

設定自動並行度為auto

LEO1@LEO1> alter session set parallel_degree_policy=auto;

Session altered.

LEO1@LEO1> select table_name,degree from user_tables where table_name in ('LEO3','LEO4');

TABLE_NAME DEGREE

---------- --------------------

LEO3                6

LEO4          DEFAULT

LEO1@LEO1> select count(*) from leo3;

  COUNT(*)

----------

     72017

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';

STATISTIC                      LAST_QUERY SESSION_TOTAL

------------------------------ ---------- -------------

Allocation Height                       0             0

LEO1@LEO1> select count(*) from leo4;

  COUNT(*)

----------

     72018

LEO1@LEO1> select * from v$pq_sesstat where statistic='Allocation Height';

STATISTIC                      LAST_QUERY SESSION_TOTAL

------------------------------ ---------- -------------

Allocation Height                       0             0

小結:無論是直接指定並行度還是使用預設並行度,oracle都調整為0,這是因為oracle認為資料量較小(7w)沒有必要使用並行技術。


用一個並行的SQL示例,比較10391事件和 V$PQ_TQSTAT結果的異同

10391事件可以跟蹤整個並行流程,我們檢視10391事件trace檔案就可以知道sql語句並行執行情況

第一步  第二步  第三步  第四步

LEO1@LEO1> drop table leo5 purge;                           清理環境

Table dropped.

LEO1@LEO1> create table leo5 as select * from dba_objects;       建立leo5

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO5')  表分析

PL/SQL procedure successfully completed.

LEO1@LEO1> alter session set events '10391 trace name context forever,level 12';   啟動10391事件

Session altered.

在執行下面3條語句的時候記下當前時間,幹什麼呢後面會揭曉(非常重要哦)

2013-01-25 15:25   這是我的時間

LEO1@LEO1> select /*+ parallel(leo5,4) */ count(*) from leo5;   執行3sql語句

  COUNT(*)

----------

     72011

LEO1@LEO1> select /*+ parallel(leo5,4) */ count(*) from leo5;好在10391事件trace檔案中找到並行資訊

  COUNT(*)

----------

     72011

LEO1@LEO1> select /*+ parallel(leo5,4) */ count(*) from leo5;我們執行幾次就要在trace檔案中找到幾段

  COUNT(*)

----------

     72011

下面還可以執行一些其他SQL語句用於刷trace,後面有解釋為什麼

LEO1@LEO1> alter session set events '10391 trace name context off';   關閉10391事件

Session altered.

LEO1@LEO1> select name,value from v$diag_info where name='Default Trace File'; 當前會話寫入trace檔名

NAME                           VALUE

--------------------------------------------------  -------------------------------------------------------------------------------

Default  Trace  File               /u01/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_ora_16433.trc

[oracle@leonarding1 trace]$ pwd

/u01/app/oracle/diag/rdbms/leo1/LEO1/trace   oracle 11goracle 10g trace檔案所在目錄不同請注意

LEO1@LEO1> !vim /u01/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_ora_16433.trc   開啟trace檔案選取有用資訊,真的有可用資訊嗎?真的嘛?

這時你可能會發現從上找到下,翻來覆去的找啊找,就是沒有並行salve程式資訊,難道oracle 11g不把並行資訊寫入trace檔案嘛,這是真的嘛?=> NO不要相信你看到的,真理往往站在少數人身邊。那大家會說並行資訊到底在哪裡啊在哪裡?其實oracle跟我們玩了一次躲貓貓,它把資訊藏在了log buffer cache 中,因為還沒有刷到trace檔案裡,所以我們才沒看到,那大家進一步會問oracle多長時間清理一次緩衝區髒資料呢,反正我的oracle 11g資料庫大約每11分鐘刷一次(oracle 10g相對較短所以大家在10g上會立刻看到),這也和緩衝區中資料量有關,如果在生產環境中不停的產生trace log可能時間間隔會縮短,只有把並行資訊刷到trace檔案中,我們才能看到,這就是原因所在!

ORACLE  11G

2013-01-25 15:25

LEO1@LEO1> select /*+ parallel(leo5,4) */ count(*) from leo5;   

*** 2013-01-25 15:25:32.042

kxfrDmpUpdSys

        allocated slave set: nsset:1 nbslv:4 tinst=1 ipq=0

          Slave set 0: #nodes:1

          Min # slaves 4: Max # slaves:4

            List of Slaves:

              slv:  0 nid:0 instid:1 sid:00

              slv:  1 nid:0 instid:1 sid:01

              slv:  2 nid:0 instid:1 sid:02

              slv:  3 nid:0 instid:1 sid:03

            List of Nodes:

              node 0

這是第一條語句的並行資訊,對著時間找比較容易,使用了4slave程式

ORACLE  10G

kxfrDmpUpdSys

        allocated slave set: nsset:1 nbslv:4

          Slave set 0: #nodes:1

          Min # slaves 4: Max # slaves:4

            List of Slaves:

              slv 0 nid:0

              slv 1 nid:0

              slv 2 nid:0

              slv 3 nid:0

            List of Nodes:

              node 0

11G要比10G的多些資訊,包括例項資訊  會話資訊等

*** 2013-01-25 15:25:34.115

        dumping system information

          arch:255 (unknown)

          sess:133 myiid:1 mynid:1 ninst:1 maxiid:1, mnodes:0

          Instances running on that system:

            inum:0 iid:1

kxfrDmpUpdSys

        allocated slave set: nsset:1 nbslv:4 tinst=1 ipq=0

          Slave set 0: #nodes:1

          Min # slaves 4: Max # slaves:4

            List of Slaves:

              slv:  0 nid:0 instid:1 sid:00

              slv:  1 nid:0 instid:1 sid:01

              slv:  2 nid:0 instid:1 sid:02

              slv:  3 nid:0 instid:1 sid:03

            List of Nodes:

              node 0

這是第二條語句的並行資訊

*** 2013-01-25 15:25:37.975

        dumping system information

          arch:255 (unknown)

          sess:133 myiid:1 mynid:1 ninst:1 maxiid:1, mnodes:0

          Instances running on that system:

            inum:0 iid:1

kxfrDmpUpdSys

        allocated slave set: nsset:1 nbslv:4 tinst=1 ipq=0

          Slave set 0: #nodes:1

          Min # slaves 4: Max # slaves:4

            List of Slaves:

              slv:  0 nid:0 instid:1 sid:00

              slv:  1 nid:0 instid:1 sid:01

              slv:  2 nid:0 instid:1 sid:02

              slv:  3 nid:0 instid:1 sid:03

            List of Nodes:

              node 0

這是第三條語句的並行資訊

比較10391事件和 V$PQ_TQSTAT檢視

LEO1@LEO1> select dfo_number,tq_id,server_type,num_rows,bytes,process from v$pq_tqstat;

DFO_NUMBER      TQ_ID SERVER_TYPE            NUM_ROWS      BYTES PROCESS

---------- ---------- -------------------- ---------- ---------- --------------------

         1          0 Producer                      1         36 P003

         1          0 Producer                      1         36 P001

         1          0 Producer                      1         36 P002

         1          0 Producer                      1         36 P000

         1          0 Consumer                     4        144 QC

都顯示使用了4個並行服務程式

小結:本小題做起來並不難,但往往得不到自己想要的結果,做了一個下午終於撥雲見日感慨萬千,賦詩一首,留念於此!走起

遇到問題誤急躁

                          想想這是為何因

                                                    多問朋友多交流

                                                                              答案自然來敲門


分別演示一個DDLDML操作的並行執行示例

(1)    並行常用於:1.FTS_Full Table Scan

                                        2.IFFS_Index Fast Full Scan

                                        3.分割槽表

2)這個小題在我的一篇blog中有非常詳細闡述和實驗,感興趣的朋友可以去看一看

oracle 並行原理深入解析及案例精粹》

3)這裡我把需要注意的地方和一些應用場合跟大家一起交流交流

並行查詢和並行DDL可以無障礙使用並行,如果想使用並行DML,就需要啟動會話DML並行功能

alter session enable parallel dml;

4)實驗

DDL並行測試

如果想捕捉DDL並行資訊,我們可以採用10046事件來過濾並行資訊,因為10046事件記錄了sql解析、執行、取操作的效能指標和等待事件,在等待事件中我們就可以看到PX事件來說明DDL的並行操作

LEO1@LEO1> drop table leo6 purge;     清理環境

Table dropped.

LEO1@LEO1> alter session set events '10046 trace name context forever,level 12';    啟動10046事件

Session altered.

LEO1@LEO1> create table leo6 parallel 4 as select * from dba_objects;  使用4個並行程式來建立表

Table created.

LEO1@LEO1> create index leo6_index on leo6(object_id) parallel 4;   使用4個並行程式來建立索引

Index created.

LEO1@LEO1> alter index leo6_index rebuild parallel 4;   重建索引可以這種寫法

Index altered.

LEO1@LEO1> alter session set events '10046 trace name context off';    關閉10046事件

Session altered.

LEO1@LEO1> select name,value from v$diag_info where name='Default Trace File'; 當前會話寫入trace檔名

NAME                           VALUE

--------------------------------------------------  -------------------------------------------------------------------------------

Default  Trace  File               /u01/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_ora_16433.trc

注:oracle提供了一個tkprof工具來對trace檔案進行格式化翻譯,過濾出有用的資訊

LEO1@LEO1> !tkprof /u01/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_ora_16433.trc

/u01/app/oracle/diag/rdbms/leo1/LEO1/trace/10046.txt sys=no

TKPROF: Release 11.2.0.1.0 - Development on Fri Jan 25 17:21:09 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

LEO1@LEO1> !vim /u01/app/oracle/diag/rdbms/leo1/LEO1/trace/10046.txt     檢視日誌

create table leo6 parallel 4 as select * from dba_objects    我只把並行資訊擷取出來

Rows     Row Source Operation

-------  ---------------------------------------------------

      4  PX COORDINATOR  (cr=1347 pr=0 pw=0 time=365787 us)

      0   PX SEND QC (RANDOM) :TQ20001 (cr=0 pr=0 pw=0 time=0 us cost=132 size=14151348 card=68364)

      0    LOAD AS SELECT  (cr=0 pr=0 pw=0 time=0 us)

      0     VIEW  DBA_OBJECTS (cr=0 pr=0 pw=0 time=0 us cost=132 size=14151348 card=68364)

      0      UNION-ALL  (cr=0 pr=0 pw=0 time=0 us)

      0       TABLE ACCESS BY INDEX ROWID SUM$ (cr=2 pr=0 pw=0 time=0 us cost=0 size=26 card=1)

      1        INDEX UNIQUE SCAN I_SUM$_1 (cr=1 pr=0 pw=0 time=0 us cost=0 size=0 card=1)(object id 956)

      0       TABLE ACCESS BY INDEX ROWID OBJ$ (cr=0 pr=0 pw=0 time=0 us cost=3 size=30 card=1)

      0        INDEX RANGE SCAN I_OBJ1 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)(object id 36)

      0       BUFFER SORT (cr=0 pr=0 pw=0 time=0 us)

     0        PX RECEIVE  (cr=0 pr=0 pw=0 time=0 us)

      0         PX SEND ROUND-ROBIN :TQ20000 (cr=0 pr=0 pw=0 time=0 us)

  72011          FILTER  (cr=1342 pr=0 pw=0 time=1481001 us)

  72877           PX COORDINATOR  (cr=9 pr=0 pw=0 time=1519912 us)

      0            PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=73 size=9030052 card=72823)

      0             HASH JOIN  (cr=0 pr=0 pw=0 time=0 us cost=73 size=9030052 card=72823)

      0              PX RECEIVE  (cr=0 pr=0 pw=0 time=0 us cost=2 size=1584 card=88)

      0               PX SEND BROADCAST :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=1584 card=88)

      0                PX BLOCK ITERATOR (cr=0 pr=0 pw=0 time=0 us cost=2 size=1584 card=88)

      0                 TABLE ACCESS FULL USER$ (cr=0 pr=0 pw=0 time=0 us cost=2 size=1584 card=88)

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  os thread startup                              12        0.03          0.28

  PX Deq: Join ACK                               12        0.00          0.00

  PX Deq: Parse Reply                            12        0.03          0.06

  reliable message                                5        0.00          0.00

  PX Deq: Execute Reply                          90        0.33          1.18

  PX Deq: Table Q Normal                          3        0.00          0.00

  PX Deq: Signal ACK RSG                          1        0.00          0.00

  enq: CR - block range reuse ckpt                3        0.01          0.03

  log file sync                                   1        0.00          0.00

  PX Deq: Signal ACK EXT                          7        0.00          0.00

  PX Deq: Slave Session Stats                     8        0.00          0.00

  SQL*Net message to client                       1        0.00          0.00

  SQL*Net message from client                     1        7.71          7.71

create index leo6_index on leo6(object_id) parallel 4

Rows     Row Source Operation

-------  ---------------------------------------------------

      3  PX COORDINATOR  (cr=5 pr=0 pw=0 time=82 us)

      0   PX SEND QC (ORDER) :TQ10001 (cr=0 pr=0 pw=0 time=0 us)

      0    INDEX BUILD NON UNIQUE LEO6_INDEX (cr=0 pr=0 pw=0 time=0 us)(object id 0)

      0     SORT CREATE INDEX (cr=0 pr=0 pw=0 time=0 us)

      0      PX RECEIVE  (cr=0 pr=0 pw=0 time=0 us cost=85 size=1189266 card=91482)

      0       PX SEND RANGE :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=85 size=1189266 card=91482)

      0        PX BLOCK ITERATOR (cr=0 pr=0 pw=0 time=0 us cost=85 size=1189266 card=91482)

      0         TABLE ACCESS FULL LEO6 (cr=0 pr=0 pw=0 time=0 us cost=85 size=1189266 card=91482)

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  reliable message                                4        0.00          0.00

  enq: KO - fast object checkpoint                1        0.01          0.01

  PX Deq: Join ACK                                1        0.00          0.00

  PX Deq: Parse Reply                             2        0.00          0.00

  PX Deq: Execute Reply                          58        0.16          0.50

  PX Deq: Table Q qref                            2        0.00          0.00

  db file sequential read                         4        0.00          0.00

  enq: CR - block range reuse ckpt                2        0.09          0.14

  log file sync                                   1        0.02          0.02

  PX Deq: Signal ACK EXT                          7        0.06          0.08

  PX Deq: Slave Session Stats                     3        0.00          0.00

alter index leo6_index rebuild parallel 4

Rows     Row Source Operation

-------  ---------------------------------------------------

      3  PX COORDINATOR  (cr=5 pr=0 pw=0 time=52 us)

      0   PX SEND QC (ORDER) :TQ10001 (cr=0 pr=0 pw=0 time=0 us)

      0    INDEX BUILD NON UNIQUE LEO6_INDEX (cr=0 pr=0 pw=0 time=0 us)(object id 0)

      0     SORT CREATE INDEX (cr=0 pr=0 pw=0 time=0 us)

      0      PX RECEIVE  (cr=0 pr=0 pw=0 time=0 us)

      0       PX SEND RANGE :TQ10000 (cr=0 pr=0 pw=0 time=0 us)

      0        PX BLOCK ITERATOR (cr=0 pr=0 pw=0 time=0 us)

      0         INDEX FAST FULL SCAN LEO6_INDEX (cr=0 pr=0 pw=0 time=0 us)(object id 74027)

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  PX Deq: Join ACK                                5        0.00          0.00

  PX Deq: Parse Reply                             4        0.00          0.00

  PX Deq: Execute Reply                          50        0.04          0.19

  PX Deq: Table Q qref                            3        0.00          0.00

  db file sequential read                         5        0.00          0.00

  reliable message                                3        0.00          0.00

  enq: CR - block range reuse ckpt                3        0.01          0.02

  PX Deq: Signal ACK EXT                          4        0.03          0.03

  PX Deq: Slave Session Stats                     3        0.00          0.00

小結:上面的PX資訊充分說明了我們在進行DDL操作時使用了並行技術

DML並行測試

前提:首先說明oracleDML並行操作是有限制的,必須設定啟用會話並行度,否則即使SQL指定了並行,oracle也不會執行DML並行操作

其次oracle只對partition table分割槽表做並行處理(有幾個分割槽就開幾個並行),普通表oracle不做並行處理(即使設定了並行度oracle也不做並行處理),只限delete update merge操作

我們做個insert並行測試吧

insert測試中只有insert into ...... select ......做並行才有意義,insert into ......values ......單條插入沒有意義

LEO1@LEO1> explain plan for insert /*+ parallel(leo5 4) */ into leo5 select /*+ parallel(leo6 2) */ * from leo6;

Explained. 這種寫法只生成執行計劃不做實際插入操作,下面我們來看看執行計劃情況

LEO1@LEO1> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------------------------------------------------

Plan hash value: 987566897

------------------------------------------------------------------------------------------------------------------

| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

------------------------------------------------------------------------------------------------------------------

|   0 | INSERT STATEMENT         |          | 60249 |    11M|   170   (1)| 00:00:03 |        |      |            |

|   1 |  LOAD TABLE CONVENTIONAL | LEO5     |       |       |            |          |        |      |            |

|   2 |   PX COORDINATOR         |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)   | :TQ10000 | 60249 |    11M|   170   (1)| 00:00:03 |  Q1,00 | P->S | QC (RAND)  |

|   4 |     PX BLOCK ITERATOR    |          | 60249 |    11M|   170   (1)| 00:00:03 |  Q1,00 | PCWC |            |

|   5 |      TABLE ACCESS FULL   | LEO6     | 60249 |    11M|   170   (1)| 00:00:03 |  Q1,00 | PCWP |            |

------------------------------------------------------------------------------------------------------------------

小結:執行計劃 insertselect操作別分使用了並行,它們是相互獨立的互不干涉


並行  執行計劃  PARALLEL_DEGREE_POLICY  10391  V$PQ_TQSTAT  DDL  DML



2013.1.25
天津&winter
分享技術~成就夢想
Blog

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

相關文章