並行執行(parallel execution)是Oracle企業版才有的特性(標準版中沒有這個特性),指能夠將壹個大型串行任務(任何DML,或者壹般的DDL)物理地劃分為多個較小的部分,這些較小的部分可以同時得到處理。
並行包括:
並行查詢:這是指能使用多個操作系統進程或線程來執行壹個查詢。Oracle會發現能並行執行的操作(如全表掃描或大規模排序),並創建壹個查詢計劃來實現)。
並行DML(PDML):這在本質上與並行查詢很相似,但是PDML主要是使用並行處理來執行修改(INSERT、UPDATE、DELETE和MERGE)。
並行DDL:並行DDL是指Oracle能並行地執行大規模的DDL操作。例如,索引重建、創建壹個新索引、數據加載以及大表的重組等都可以使用並行處理。
並行恢復:這是指數據庫能並行地執行實例(甚至介質)恢復,以減少從故障恢復所需的時間。
過程並行化:這是指能並行地運行所開發的代碼。
何時使用並行
在應用並行執行之前,需要保證以下兩點成立:
必須有壹個非常大的任務,如對50GB數據進行全面掃描。
必須有足夠的可用資源(CPU、I/O、內存)。在並行全面掃描50GB數據之前,妳要確保有足夠的空閑CPU(以容納並行進程),還要有足夠的I/O通道。
如果只有壹個小任務(通常OLTP系統中執行的查詢就是這種典型的小任務),或者妳的可用資源不足(這也是OLTP系統中很典型的情況),其中CPU和I/O資源通常已經得到最大限度的使用,那就根本不用考慮並行執行。
如果壹個任務只需要幾秒(或更短時間)就能串行地完成,引入並行執行後,相關的管理開銷可能會讓整個過程花費更長的時間。
舉例如,寫壹頁文檔若12個人來寫,需要開會分段等,可能並不如壹個人來寫更快。而如果寫1200頁,12個人寫需要的時間只為原來的1/12,就算分配任務可能也就1/12,還是比壹個人寫要快多了。
並行查詢
並行查詢允許將壹個SQL SELECT語句劃分為多個較小的查詢,每個部分的查詢並發地運行,然後會將各個部分的結果組合起來,提供最終的答案。
在並行進程和掃描文件之間並不存在1對1映射,可以多個進程掃描同壹個文件。
各個並行進程可稱為並行執行服務器(parallel execution server),有時也稱為並行查詢(parallel
query,PQ)從屬進程。各個並行執行服務器都是單獨的會話,就像是專業服務器進程壹樣連接數據庫。每個並行執行服務器分別負責掃描表中壹個部分(各
個部分都不重疊),匯總其結果子集,將其輸出發回給協調服務器(即原始會話的服務器進程),它再將這些子結果匯總為最終答案。
在默認情況下,Oracle是不啟用並行查詢的。啟用並行查詢有多種方法,可以直接在查詢中使用壹個提示,或者修改表要求考慮並行執行路徑等。
並行查詢方法
1)暗示hints式,臨時有效
select /*+parallel(table_name num)*/ count(*) from table_name;
多表關聯時多表並行:
select /*+parallel(table_name1,num1) parallel(table_name2,num2)*/ count(*) from table_name1, table_name2;
2)alter table對象式,長期有效
alter table table_name parallel num;
3)alter session會話式,會話生命周期有效
alter session force parallel query parallel num;
4)並行DDL式,會話生命周期有效
alter session enable parallel dml;
對於前兩種方式,若省略num則Oracle將自動根據負載確定並行度。並行度要隨著系統上工作負載的增減而變化。如果有充足的空閑資源,並行度會
上升;如果可用資源有限,並行度則會下降。這樣就不會為機器強加壹個固定的並行度。利用這種方法,允許Oracle動態地增加或減少查詢所需的並發資源
量。
查看默認並行數
1)確定會話SID
select sid from v$mystat where rownum = 1;
2)在其他會話中查詢
select sid,qcsid,server#,degree from v$px_session where qcsid = num;
壹般而言,如果能訪問盡可能多的資源(CPU、內存和I/O),並行執行就能最好地發揮作用。但這並不是說如果整個數據集都在壹個磁盤上,就從並行
查詢得不到任何好處。不過如果整個數據集都在壹個磁盤上,可能確實不如使用多個磁盤那樣能有更多收獲。即使使用壹個磁盤,在響應時間上也可能可以得到壹定
的速度提升。原因在於:給定的壹個並行執行服務器在統計行時並不讀取這些行,反之亦然。所以,與執行串行相比,兩個並行執行服務器可以在更短的時間內完成
所有行的統計。
數據分布在多個物理設備上可以提高I/O,如表分區、跨磁盤等。
在Oracle 11g Release2及以上版本中,引入了壹項新功能來限制資源過度使用:並行語句排除(Parallel
Statement
Queuing,PSQ)。使用PSQ時,數據庫會限制並發執行的並行查詢數,並把更多的並行請求放在壹個執行隊列中。CPU資源用盡時數據庫會阻止新的
請求變為活動狀態。這些請求並沒有失敗,它們只是會延遲開始,也就是說它們將排隊。資源可用時,數據庫就會開始執行隊列中的查詢。
並行DML
Oracle文檔將並行DML(PDML)壹詞的範圍限制為只包括INSERT、UPDATE、DELETE和MERGE(不像平常的DML那樣還
包括SELECT)。在PDML期間,Oracle可以使用多個並行執行服務器來執行INSERT、UPDATE、DELETE或MERGE,而不是只利
用壹個串行進程。在壹個有充足I/O帶寬的多CPU主機上,對於大規模的DML操作,可能會得到很大的速度提升。
不過,不能把PDML當成提高OLTP應用速度的壹個特性。因為並行操作設計為要充分、完全地利用壹臺機器上的所有資源。通過這種設計,壹個用戶可
以完全使用機器上的所有磁盤、CPU和內存。在某些數據倉庫中(有大量數據,而用戶很少),這可能正是妳想要的。而在壹個OLTP系統中(大量用戶都在做
很短、很快的事務),可能就不能希望如此了,妳不想讓用戶能夠完全占用機器資源。
類似於Oracle執行的分布式查詢,PDML操作采用同樣的方式執行,即每個並行執行服務器相當於壹個單獨數據庫實例中的壹個進程。這些事務都結束後,會執行壹個相當於快速2PC的過程來提交這些單獨的獨立事務。這些事務要麽都由PDML協調會話提交,要麽無壹提交。
由於PDML采用的壹種偽分布式的實現,因此存在壹些限制:
PDML操作期間不支持觸發器。這是壹個很合理的限制,因為觸發器可能會向更新增加大量開銷,而妳使用PDML的本來目的是為了更快壹些,這兩方面是矛盾的,不能放在壹起。
PDML期間,不支持某些聲明方式的引用完整性約束,因為表中的每壹片(部分)會在單獨的會話中作為單獨的事務進行修改。例如,PDML操作不支持自引用完整性。如果真的支持自引用完整性,可能會出現死鎖和其他鎖定問題。
在提交或回滾之前,不能訪問用PDML修改的表。
PDML不支持高級復制(因為復制特性的實現要基於觸發器)。
不支持延遲約束(也就是說,采用延遲模式的約束)。
如果表是分區的,PDML只可能在有位圖索引或LOB列的表上執行,而且並行度取決於分區數。在這種情況下,無法在分區內並行執行壹個操作,因為每個分區只有壹個並行執行服務器來處理。
執行PDML時不支持分布式事務。
PDML不支持聚簇表。
並行DDL
從維護的觀點看,以及從管理的角度來說,並行DDL才是Oracle中並行執行最突出的優點。如果認為並行查詢主要是為最終用戶設計的,那麽並行
DDL則是為DBA/開發人員設計的。如果沒有並行執行,DBA將很難真正充分利用硬件的全部能力。但如果利用並行執行,則完全可以做到。以下SQL
DDL命令允許“並行化”:
CREATE INDEX:多個並行執行服務器可以掃描表、對數據排序,並把有序的段寫出到索引結構。
CREATE TABLE AS SELECT:執行SELECT的查詢可以使用並行查詢來執行,表加載本身可以並行完成。
ALTER INDEX REBUILD:索引結構可以並行重建。
ALTER TABLE MOVE:表可以並行移動。
ALTER TABLE SPLIT|COALESCE PARTITION:單個表分區可以並行地分解或合並。
ALTER INDEX SPLIT PARTITION:索引分區可以並行地分解。
前4個命令還適用於單個的表/索引分區,也就是說,可以並行地MOVE壹個表的單個分區。
並行DDL和使用外部表的數據加載
利用並行DDL,再加上外部表,就能通過壹個簡單的CREATE TABLE AS SELECT or INSERT /*+ APPEND
*/來實現並行直接路徑加載。不用再編寫腳本,不必再分解文件,也不用協調要運行的N個腳本。簡單地說,通過結合並行DDL和外部表,不僅提供了純粹的易
用性,而且全無性能損失。
並行DDL和區段截斷
並行DDL依賴於直接路徑操作。也就是說,數據不傳遞到緩沖區緩存以便以後寫出;而是由壹個操作(如CREATE TABLE AS
SELECT)來創建新的區段,並直接寫入這些區段,數據直接從查詢寫到磁盤(放在這些新分配的區段中)。每個並行執行服務器執行自己的部分CREATE
TABLE AS SELECT工作,並且都會寫至自己的區段。INSERT /*+ APPEND
*/(直接路徑插入)會在壹個段的HWM“之上“寫,每個並行執行服務器再寫至其自己的壹組區段,而不會與其他並行執行服務器***享。因此,如果執行壹個並
行CREATE TABLE AS
SELECT,並使用4個並行執行服務器來創建表,就至少有4個分區,可能還會更多。每個並行執行服務器會分配其自己的區段,向其寫入,等填滿時,再分配
另壹個新的區段,並行執行服務器不會使用由其他並行執行服務器非品牌的區段。
在數據倉庫環境中,執行壹個大規模的加載之後,這可能導致“過渡浪費“。假設妳想加載1,010MB的數據(大約1GB),而且正在使用壹個有
100MB區段的表空間,妳決定使用10個並行執行服務器來加載這個數據。每個並行執行服務器先分配其自己的100MB區段(總***會有10個100MB的
區段),並在其中填入數據。由於每個並行執行服務器都要加載101MB的數據,所以它會填滿第壹個區段,然後再繼續分配另壹個100MB的區段,但實際上
只會使用這個區段中1MB的空間。現在就有了20區段,其中10個是滿的,另外10個則不同,這10個區段中都各有1MB的數據,因此,總***會有
990MB的空間是”已分配但未使用的“。下壹次加載是可以使用這個空間,但是對現在來說,妳就有了990MB的死空間。此時區段截斷(extend
trimming)就能派上用場了。Oracle會試圖取每個並行執行服務器的最後壹個區段,並將其”截斷為“可能的最小大小。
區段截斷和字典管理表空間
如果使用傳統的字典管理表空間,Oracle可以把只包含1MB數據的各個100MB區段轉變或1MB的區段。遺憾的是,(在字典管理的表空間中)
這會留下10個不連續的99MB空閑區段,因為妳的分配機制采用的是100MB區段,所以這990MB空間就會用不上!下壹次分配100MB時,往往無法
使用現有的這些空間,因為現在的情況是:有99MB的空閑空間,接下來是1MB的已分配空間,然後又是99MB空閑空間,依此類推。
區段截斷和本地管理表空間
本地管理表空間有兩種類型:UNIFORM SIZE 和AUTOALLOCATE,UNIFORM
SIZE是指表空間中的每個區段大小總是完全相同;AUTOALLOCATE則表示Oracle會使用壹種內部算法來確定每個區段應該是多大。這些方法都
能很好地解決上述問題,不過,這兩種方法的解決策略截然不同。
在字典管理的表空間中,如果請求壹個100MB區段,倘若Oracle只找到了99MB的自由區段,請求還是會失敗。與字典管理表空間不同,有AUTOALLOCATE區段的本地管理表空間可以更為靈活。為了試圖使用所有空閑空間,它可以減小所請求的空間大小。
隨著使用並行直接路徑操作向表UNIFORM_TEST加載越來越多的數據,過壹段時間後,空間利用情況會變得越來越糟糕。對此,我們可能希望使用
壹個更小的統壹區段大小,或者使用AUTOALLOCATE。壹段時間後,AUTOALLOCATE也可能生成更多的區段,但是由於會發生區段截斷,所以
空間利用情況要好得多。