oracle使用並行踩過的坑

1、並行機制的簡述sql

並行處理的機制實際上就是把一個要掃描的數據集分紅不少小數據集,Oracle會根據初始化參數 PARALLEL_MIN_SERVERS=n的值啓動幾個並行服務進程同時處理這些小數據集,最後將這些結果彙總,做爲最終的處理結果返回給用戶。session


2、並行使用場景oracle

一、Parallel query(並行查詢)ide

執行並行查詢是須要符合如下條件:性能

ASQL語句中有Hint提示,好比Parallel或者 Parallel_index測試

BSQL語句中引用的對象被設置了並行屬性。this

C、多表關聯中,至少有一個表執行全表掃描(Fulltable scan)或者跨分區的Index range SCANspa

 

二、Parallel DDL(並行DDL操做,如建表,建索引等)設計

 如:createtable xx parallel 4 as select * from xxx;orm

          create index xxx on tab_xx(column) parallel 4;

 

三、Parallel DML(並行DML操做,如insert、update、delete等)

 如:insert/*+parallel(t 2) */ into t select /*+parallel(t1 2) */ * from t1;

 

下面從以上三個場景各舉一例來講一下並行易踩的坑。

 

3、並行對執行計劃的影響

某日,開發忽然找過來:喂、DBA嗎?有個測試環境的SQL執行計劃和生產環境不同,嚴重影響測試進度。記得當時差很少是這樣的,對方向我扔了一條執行計劃有問題的SQL,而後不說話。做爲一個菜鳥,趕忙把生產執行計劃和測試環境對比了一下,發現果然不同,折騰了很久,才發現該SQL中的某個表並行度爲8,致使了執行計劃異常。記得該表是TB級的大小,是個多表管理的查詢語句,並行度爲8以後走了全表掃描(Full table scan),能夠想象是又多慢。由於是測試環境,誰作什麼操做以後沒有關閉並行就不深究了。下面看一下oracle聯機文檔:http://download.oracle.com/docs/cd/E11882_01/server.112/e10821/ex_plan.htm#PFGRF94687對並行處理的執行計劃的解讀。

SQL>createtable emp2 as select * from scott.emp;
 
SQL>altertable emp2 parallel 2;  --能夠查看dba_tables表degree列
 
SQL>explainplan for select sum(sal) from emp2 group by deptno;
 
SQL> select * fromtable(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    |         |         1|          26 |           2   (0)| 00:00:01 |          |         |                  |
|   1|  PX COORDINATOR           |         |          |           |                 |        |            |         |                 |
|   2|   PX SEND QC (RANDOM)          | :TQ10001 |  1 |          26 |           2  (0)| 00:00:01 |  Q1,01 | P->S |QC (RAND)  |
|   3|    HASH GROUP BY |         |         1 |         26 |           2  (0)| 00:00:01 |  Q1,01 | PCWP |                  |
|   4|     PX RECEIVE                  |         |         1 |         26 |           2  (0)| 00:00:01 |  Q1,01 | PCWP |                  |
|   5|      PX SEND HASH          | :TQ10000 |  1 |          26 |           2  (0)| 00:00:01 |  Q1,00 | P->P |HASH          |
|   6|       HASH GROUP BY    |         |         1 |         26 |           2  (0)| 00:00:01 |  Q1,00 | PCWP |                  |
|   7|        PX BLOCK ITERATOR |             |         1 |         26 |           2  (0)| 00:00:01 |  Q1,00 | PCWC |                  |
|   8|   TABLE ACCESS FULL| EMP2     |  1 |         26 |           2  (0)| 00:00:01 |  Q1,00 | PCWP |                  |
------------------------------------------------------------------------------------------------------------------
 
Note
-----
   -dynamic sampling used for this statement (level=2)
 
19 rows selected.

當使用了並行執行,SQL的執行計劃中就會多出一列:in-out。該列幫助咱們理解數據流的執行方法。它的一些值的含義以下:

Parallel to SerialP->S: 表示一個並行操做發送數據給一個串行操做,一般是並行incheng將數據發送給並行調度進程。

Parallel to ParallelP->P):表示一個並行操做向另外一個並行操做發送數據,疆場是兩個從屬進程之間的數據交流。

Parallel Combined with parent(PCWP): 同一個從屬進程執行的並行操做,同時父操做也是並行的。

Parallel Combined with Child(PCWC): 同一個從屬進程執行的並行操做,子操做也是並行的。

Serial to ParallelS->P: 一個串行操做發送數據給並行操做,若是select 部分是串行操做,就會出現這個狀況。


若是知道了這些含義,再去解析執行計劃的執行步驟就很容易了。這裏強調一下,在處理某些操做以後,對錶或者索引等對象開啓了並行的,必定要記得關閉,否則後果很嚴重。

 

4、並行建主鍵惟一性索引的影響

又是某日,開發欲在測試環境對某一大表建主鍵惟一性索引(前期未規劃好),語句執行了很長時間,由於其它人還需調用該表,但長時間的鎖表,形成了不可用,因而請求DBA幫助,我看了語句以後,給出建議建索引時加上並行並以nologing的方式,而後讓開發本身再去執行,可不久後,開發又找過來講仍是很慢,查看沒有任何阻塞以後,決定好好看看是否是真的很慢。通過一番折騰,終於知道慢的緣由了,建主鍵約束時不會用到並行。解決方案分兩步走,先建惟一性約束,再加主鍵約束。以下:

一、開並行重建惟一索引:

create unique index schema.xxx onschema.table_name(column1,column2) parallel 16;

二、取消並行:alter indexschema.xxx noparallel;  --索引建完後,必定記得取消並行

三、建主鍵約束:alter tableschame.xxx add constraint xxx primary key(column1,column2); --主鍵創建並行是沒有效果的

 

相關測試這裏就不演示了,測試方法很簡單,在建索引的過程當中查詢dba_tablesdegree列就好了。這裏須要強調的一點是對於表的設計規劃,前期必定要作好。


5、並行DML沒法生效

SQL> explain plan for insert/*+parallel(a,4) */ into emp2 a select * from emp;
 
Explained.
 
SQL> select * fromtable(dbms_xplan.display());
 
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
Plan hash value: 3956160932
 
---------------------------------------------------------------------------------
| Id | Operation              | Name |Rows      | Bytes | Cost (%CPU)| Time  |
---------------------------------------------------------------------------------
|   0| INSERT STATEMENT    |     |    1 |    87 |     2  (0)| 00:00:01 |
|   1|  LOAD TABLE CONVENTIONAL | EMP2 ||       |           |              |
|   2|   TABLE ACCESS FULL        | EMP     |     1 |   87 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------
 
Note
-----
   -dynamic sampling used for this statement (level=2)
 
13 rows selected.

能夠看到該DML語句在有HINT提示的狀況下沒有使用並行,那要怎樣才能使它使用並行呢?很簡單,只須要執行alter session enable parallel dml; 這裏也能夠想一下和以前的並行查詢和並行DDL是不一樣的。

SQL> alter session enable parallel dml;
 
Session altered.
 
SQL> explain plan for insert/*+parallel(a,4) */ into emp2 a select * from emp;
 
Explained.
 
SQL> select * fromtable(dbms_xplan.display());
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 883381916
 
-----------------------------------------------------------------------------------------------------------------
| Id | Operation             | Name       |Rows  | Bytes | Cost (%CPU)| Time        |          TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0| INSERT STATEMENT   |         |           1 |  87 |  2   (0)| 00:00:01 |          |          |                   |
|   1|  PX COORDINATOR          |          |             |             |                   |         |              |          |                   |
|   2|   PX SEND QC (RANDOM)         | :TQ10001 |     1 |  87 |   2  (0)| 00:00:01 |  Q1,01 | P->S |QC (RAND)|
|   3|    LOAD AS SELECT| EMP2        |             |             |                   |         |  Q1,01 | PCWP |             |
|   4|     PX RECEIVE                 |          |          1 |  87 |  2   (0)| 00:00:01 |  Q1,01 | PCWP |          |
|   5|      PX SEND ROUND-ROBIN| :TQ10000 |     1 |  87|   2  (0)| 00:00:01 |           | S->P | RND-ROBIN         |
|   6|       TABLE ACCESS FULL | EMP       |           1 |  87|   2  (0)| 00:00:01 |           |          |                   |
-----------------------------------------------------------------------------------------------------------------
 
Note
-----
   -dynamic sampling used for this statement (level=2)
 
17 rows selected.

執行以後很見效,從執行計劃重能夠很清楚的看到該DML語句利用了並行度。這裏使用的的hint的方式提示語句使用並行,若表自己設置了並行度呢?這種狀況也是同樣的,須要香執行alter session enable parallel dml; DML語句纔可使用到並行。

 

還有一個狀況須要注意的是,對於開啓並行度以後的表存在事務未提交的,後續的事務必定會失敗,報以下錯誤:ORA-12838: cannot read/modify an object after modifying it inparallel

SQL> alter table emp2 parallel 2;
 
Table altered.
 
SQL> alter session enable parallel dml;
 
Session altered.
 
SQL> insert into emp2 a select * fromemp;
 
0 rows created.
 
SQL> insert into emp2 a select * fromemp;
insert into emp2 a select * from emp
           *
ERROR at line 1:
ORA-12838: cannot read/modify an objectafter modifying it in parallel

 

該問題在寫存儲過程的時候必定要注意,事務及時提交,但這裏又涉及到一個性能問題了,因此對於表這些對象的並行度儘可能不要開啓。

 

總結:並行確實能帶來性能上的提高,效率的提升等,可是凡事都有兩面性,濫用並行的話會致使程序爭議用,資源過分的消耗,並行是會產生排序的,因此瞭解清除並行的本質,閒時使用並行,合理規劃。

相關文章
相關標籤/搜索