oracle使用並行踩過的坑


https://blog.51cto.com/wyzwl/1948035

一、並行機制的簡述

並行處理的機制實際上就是把一個要掃描的數據集分成很多小數據集,Oracle會根據初始化參數 PARALLEL_MIN_SERVERS=n的值啟動幾個並行服務進程同時處理這些小數據集,最后將這些結果匯總,作為最終的處理結果返回給用戶。

 

二、並行使用場景

1、Parallel query(並行查詢)

執行並行查詢是需要符合以下條件:

A、SQL語句中有Hint提示,比如Parallel或者 Parallel_index。

B、SQL語句中引用的對象被設置了並行屬性。

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

 

2、Parallel DDL(並行DDL操作,如建表,建索引等)

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

          create index xxx on tab_xx(column) parallel 4;

 

3、Parallel DML(並行DML操作,如insert、update、delete等)

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

 

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

 

三、並行對執行計划的影響

某日,開發突然找過來:喂、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>create table emp2 as select * from scott.emp; SQL>alter table emp2 parallel 2; --可以查看dba_tables表degree列 SQL>explain plan for select sum(sal) from emp2 group by deptno; 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 | | 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 Serial(P->S): 表示一個並行操作發送數據給一個串行操作,通常是並行incheng將數據發送給並行調度進程。

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

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

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

Serial to Parallel(S->P): 一個串行操作發送數據給並行操作,如果select 部分是串行操作,就會出現這個情況。

 

如果知道了這些含義,再去解析執行計划的執行步驟就很容易了。這里強調一下,在處理某些操作之后,對表或者索引等對象開啟了並行的,一定要記得關閉,不然后果很嚴重。

 

四、並行建主鍵唯一性索引的影響

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

1、開並行重建唯一索引:

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

2、取消並行:alter indexschema.xxx noparallel;  --索引建完后,一定記得取消並行

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

 

相關測試這里就不演示了,測試方法很簡單,在建索引的過程中查詢dba_tables表degree列就行了。這里需要強調的一點是對於表的設計規划,前期一定要做好。

 

五、並行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
 

 

該問題在寫存儲過程的時候一定要注意,事務及時提交,但這里又涉及到一個性能問題了,所以對於表這些對象的並行度盡量不要開啟。

 

總結:並行確實能帶來性能上的提升,效率的提高等,但是凡事都有兩面性,濫用並行的話會導致程序爭議用,資源過度的消耗,並行是會產生排序的,所以了解清除並行的本質,閑時使用並行,合理規划。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM