您好,登錄后才能下訂單哦!
作者:沃趣科技高級(jí)數(shù)據(jù)庫(kù)技術(shù)專家 魏興華
根據(jù)上面的介紹,你已經(jīng)知道了,一個(gè)并行操作內(nèi)一般會(huì)具有兩組PX slave進(jìn)程,一組為生產(chǎn)者,一組為消費(fèi)者。生產(chǎn)者通過table queue發(fā)送數(shù)據(jù),消費(fèi)者通過table queue接收數(shù)據(jù)。而且對(duì)于消費(fèi)者和生產(chǎn)者模型,有一個(gè)很大的限制是:一組DFO單元最多只能有兩組PX slave進(jìn)程,之所以有這個(gè)限制,一方面可能是Oracle公司為了保持并行代碼的簡(jiǎn)潔性,一方面由于每個(gè)PX slave進(jìn)程之間和每個(gè)PX slave與QC之間都要維持一個(gè)通信通道(table queue)用于傳遞消息和數(shù)據(jù),如果允許的PX slave有太多組,可能會(huì)導(dǎo)致通信通道指數(shù)級(jí)增長(zhǎng)。例如一個(gè)DOP為5的并行操作,PX slave之間需要的通道數(shù)為55,PX slave與QC之間的通道數(shù)為25,共需要(5+2)5=35個(gè)通道??上攵?,如果Oracle允許一個(gè)并行操作內(nèi)有3組PX slave,需要維持的連接數(shù)有多少,我們假設(shè)當(dāng)前服務(wù)器共運(yùn)行了50個(gè)并行,那么三組PX slave進(jìn)程產(chǎn)生的通道數(shù)為5050*50=125000個(gè),還不包括PX slave與QC之間的通道,嚇尿了不?
如果進(jìn)程之間傳遞消息的通道數(shù)多但不占用數(shù)據(jù)庫(kù)資源可能也并不是什么大的問題,但是事實(shí)不是這樣的,進(jìn)程之間傳遞消息的通道的內(nèi)存占用大小是由參數(shù)parallel_execution_message_size控制的,在11GR2版本這個(gè)參數(shù)的值為16K,在以前的各個(gè)版本這個(gè)參數(shù)的值可能大小并不一樣(每個(gè)版本都有增大的趨勢(shì)),在非RAC環(huán)境下,每個(gè)通道的大小最大可以為3parallel_execution_message_size,在RAC環(huán)境下,每個(gè)通道的大小最大可以為4parallel_execution_message_size。
例如一個(gè)DOP為20的查詢,非rac環(huán)境下通道所占用的內(nèi)存最大可能為:
PX進(jìn)程的通道內(nèi)存+QC、PX進(jìn)程之間的通道內(nèi)存=202016K3+22016K3=21120K,接近21M的內(nèi)存。
通道的內(nèi)存默認(rèn)是在large pool中分配,如果沒有配置large pool則在shared pool中分配。
計(jì)算通道內(nèi)存的公式:
單節(jié)點(diǎn)
(NN+2N)316k
RAC節(jié)點(diǎn)
(NN+2N)416k
其實(shí)不是hash join的缺陷。
我們已經(jīng)介紹過生產(chǎn)者消費(fèi)者模型,它有一個(gè)很大“缺陷”是,一個(gè)并行操作內(nèi),最多只能有2組PX slave,2組PX slave通過table queue來(lái)傳遞消息和交互數(shù)據(jù),因此在一組SLAVE在讀table queue的時(shí)候,不能同時(shí)去寫另一個(gè)table queue。是不是不太好理解?
我們通過一個(gè)例子來(lái)進(jìn)行描述:
select /*+ parallel(6) pq_distribute(b hash hash)*/ * from hash_t3 a ,hash_t1 b where a.id=b.id;
首先紅色的生產(chǎn)者PX slave掃描hash_t3表,并對(duì)掃描的記錄按照HASH分發(fā)方式把相關(guān)記錄寫入table queue TQ10000
藍(lán)色的消費(fèi)者PX slave從table queue TQ10000接收數(shù)據(jù)并構(gòu)建hash table。
上面操作結(jié)束后,紅色的生產(chǎn)者繼續(xù)掃描hash_t1表,并對(duì)掃描的記錄按照HASH分發(fā)方式寫入table queue TQ10001
藍(lán)色的消費(fèi)者PX slave從table queue TQ10001接收數(shù)據(jù),并與上面的HASH TABLE做探測(cè),但是結(jié)果并不能寫入table queue TQ10002,而是先暫時(shí)緩存起來(lái)(hash join buffered的由來(lái))
等HASH分發(fā)完成之后(也就是這兩組PX slave不活躍以后),然后由一組PX slave把結(jié)果集通過table queue TQ10002發(fā)送給QC。
為什么要這樣?貌似是沒有道理的。
這就是因?yàn)閔ash分發(fā)要求對(duì)hash join的右邊也要進(jìn)行分發(fā),分發(fā)操作涉及了2組PX slave進(jìn)程,一組負(fù)責(zé)掃描,一組負(fù)責(zé)接收數(shù)據(jù),也就是一組PX slave把掃描的數(shù)據(jù)寫入table queue,一組負(fù)責(zé)從table queue讀取數(shù)據(jù),這個(gè)時(shí)候不能 再進(jìn)行數(shù)據(jù)的分發(fā)操作,因?yàn)閖oin的結(jié)果集不能寫入另一個(gè)table queue TQ10002。
如果結(jié)果集較大的話,這個(gè)可能在一定程度上會(huì)導(dǎo)致消耗很多臨時(shí)表空間,導(dǎo)致大量的磁盤讀寫IO,進(jìn)而引起性能降低。
如果確實(shí)產(chǎn)生了這種情況,可以通過改用broadcast分發(fā)來(lái)避免出現(xiàn)這種情況,因?yàn)閎roadcast分發(fā)對(duì)于hash join的右邊并不需要進(jìn)行分發(fā)
select /*+ parallel(6) pq_distribute(b broadcast none)*/ * from hash_t3 a ,hash_t1 b where a.id=b.id;
例如改成broadcast后,hash join buffered操作已經(jīng)消失了。
我們有必要介紹一下布隆過濾,它在11GR2之后版本的并行里有非常大的作用。bloom filter并非Oracle的發(fā)明,bloom filter技術(shù)出現(xiàn)的時(shí)候Oracle軟件還未誕生,它在1970年由Burton H.Bloom開發(fā)出來(lái),布隆過濾到什么?
布隆過濾或者說布隆過濾器,是一種數(shù)據(jù)結(jié)構(gòu),它能夠快速的判斷一個(gè)數(shù)據(jù)是否屬于一個(gè)集合,hash join本身是非常消耗資源的,也是非常慢的,布隆過濾比hash join快很多。
關(guān)于布隆過濾的詳細(xì)介紹請(qǐng)參照:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html
布隆過濾器基于一個(gè)有M位的數(shù)組,例如上圖數(shù)組的大小有18位,初始化的時(shí)候全部的值都為0,如果要理解布隆過濾是如何工作的,必須要知道在什么情況下,這些標(biāo)志位需要置為1,上圖中{X,Y,Z}代表著一個(gè)集合,這個(gè)集合有3個(gè)值(元素),仔細(xì)觀察每一個(gè)值都延伸出了三個(gè)線,在這里代表著每一個(gè)值都經(jīng)過3個(gè)HASH函數(shù)計(jì)算,計(jì)算出來(lái)的值的范圍是從0-17(數(shù)組的長(zhǎng)度),例如,X經(jīng)過3次HASH函數(shù)計(jì)算,值分別為:1,3,13,然后對(duì)應(yīng)的標(biāo)志位被置為1,Y,Z同理把相應(yīng)的標(biāo)志位置為1。經(jīng)過一番HASH計(jì)算,{X,Y,Z}集合的所有元素都已經(jīng)經(jīng)過了HASH計(jì)算,對(duì)應(yīng)的標(biāo)志位也都置為了1,然后我們?cè)偬綔y(cè)另一個(gè)集合,這里另一個(gè)集合的元素為W,W同樣需要經(jīng)過相同的3個(gè)HASH函數(shù)計(jì)算,并且檢測(cè)對(duì)應(yīng)的位置是否為1,如果對(duì)應(yīng)的位置都為一,那么W可能(僅僅是可能)屬于這個(gè)集合,如果有任何的位置不為1,那么這個(gè)W一定不屬于這個(gè)集合。由于布隆過濾并不對(duì)值進(jìn)行精確的匹配(而HASH JOIN是需要精確匹配的),因此可能會(huì)有一些不該屬于集合的值穿越了布隆過濾器。
布隆過濾器有如下特點(diǎn):
構(gòu)建布隆過濾數(shù)組要求的內(nèi)存非常小,經(jīng)??梢酝耆湃朐贑PU的cache中。當(dāng)然布隆過濾的數(shù)組越大,布隆過濾誤判的可能性也就越小。
由于不需要精確匹配,因此布隆過濾的速度非常的快,但是有一些不該出現(xiàn)的值可能會(huì)穿越布隆過濾器。
布隆過濾有啥用呢?也許你是一位有著豐富經(jīng)驗(yàn)的老DBA,那么你對(duì)PX Deq Credit: send blkd 、PX Deq Credit: need buffer等待事件也許就比較熟悉。經(jīng)過上面的介紹,我們已經(jīng)具備了很多的知識(shí),table queue,生產(chǎn)者消費(fèi)者模型等等,一組消費(fèi)者PX slave寫入table queue,另一組通過讀取table queue來(lái)獲取數(shù)據(jù),完成進(jìn)程間數(shù)據(jù)的傳遞,但是一定會(huì)出現(xiàn)一種情況,當(dāng)一組生產(chǎn)者PX slave在往table queue中寫入數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)table que中的內(nèi)存已經(jīng)滿了,沒有剩余內(nèi)存可以寫了,這種情況大部分時(shí)候都意味著消費(fèi)者PX slave從table queue中消費(fèi)數(shù)據(jù)過慢,過慢最大可能原因是由于消費(fèi)者不得不把table queue中讀取到的數(shù)據(jù)溢出到磁盤,從內(nèi)存讀取數(shù)據(jù)寫入磁盤是個(gè)很慢的操作,因此在這種情況下,就會(huì)遭遇PX Deq Credit: send blkd 、PX Deq Credit: need buffer等待,如何優(yōu)化?這種情況下,布隆過濾就發(fā)揮了作用。
如果優(yōu)化器認(rèn)為表X返回1000條記錄,表Y需要掃描一億條記錄,但是經(jīng)過HASH JOIN后,有90%都不需要返回,這種情況下使用布隆過濾在進(jìn)行HASH分發(fā)前預(yù)HASH JON。這樣經(jīng)過布隆過濾器,有大量的記錄就被布隆過濾器所淘汰,最后HASH JOIN右邊的結(jié)果集就變得非常小,也就讓HASH 分發(fā)的數(shù)據(jù)量變得非常的小,大大減少了出現(xiàn)PX Deq Credit: send blkd 、PX Deq Credit: need buffer的概率。如果不使用布隆過濾,進(jìn)程不得不傳遞大量的數(shù)據(jù)給另一組進(jìn)程,增加了內(nèi)存,CPU,增加了兩組進(jìn)程的進(jìn)程間競(jìng)爭(zhēng)。
不要期待布隆過濾是完美的,他能消除掉大部分的行,但是不是 所有的行,因此有一些不需要的數(shù)據(jù)會(huì)穿過布隆過濾器達(dá)到第二組進(jìn)程。
無(wú)論你使用的是手工指定DOP,還是使用11G的AUTO DOP,運(yùn)行時(shí)的DOP都有可能與你預(yù)期的不一樣:可能被降級(jí)。可能會(huì)有很多種原因?qū)е虏⑿斜唤档?,例如,?dāng)前系統(tǒng)中可用的并行進(jìn)程已經(jīng)不能滿足需要的DOP,或者你已經(jīng)使用了Oracle的資源管理器對(duì)并行度做了限制,等等。
監(jiān)控并行度降低的最好工具是oracle 12.1版本的SQL MONITORING,例如:
如上圖,在【一般信息】部分,將你的鼠標(biāo)放在Execution Plan部分的藍(lán)色小人上,將會(huì)出現(xiàn)一些并行度的信息,例如上圖中,運(yùn)行時(shí)間的DOP為4,實(shí)際請(qǐng)求的并行服務(wù)進(jìn)程為10,實(shí)際分配的并行服務(wù)進(jìn)程為4,并行度被降低的百分比為60%。
為了找出語(yǔ)句被降級(jí)的理由,你可以點(diǎn)擊【計(jì)劃統(tǒng)計(jì)信息】部分,PX COORDINATOR行源的其他列,如下圖,用紅色框標(biāo)記:
點(diǎn)擊后出現(xiàn):
以下是被降級(jí)的一些代碼說明:
350 DOP downgrade due to adaptive DOP
351 DOP downgrade due to resource manager max DOP
352 DOP downgrade due to insufficient number of processes
353 DOP downgrade because slaves failed to join
我這里的情況是,由于系統(tǒng)可以使用的并行進(jìn)程不足導(dǎo)致分配并行資源失敗。
如果你不方便使用EMCC,也可以通過視圖觀察到并行度降級(jí)的情況,但是被降級(jí)的理由,暫時(shí)還沒有視圖反應(yīng)(或者我還不知道,如果你知道請(qǐng)告訴我)
DEGREE 列為實(shí)際的并行度,REQ_DEGREE 為請(qǐng)求的并行度。
有一些手段可以避免并行度降級(jí),例如如果使用的是ORACLE 11G版本,可以使用自動(dòng)并行管理功能,然后結(jié)合在語(yǔ)句級(jí)指定并行度。因?yàn)樽詣?dòng)并行度功能一單被打開,并行語(yǔ)句排隊(duì)功能將被啟用,如果語(yǔ)句運(yùn)行時(shí)發(fā)現(xiàn)沒有足夠的可用并行進(jìn)程,那么會(huì)排隊(duì)等待,直到有滿足目標(biāo)的可用并行進(jìn)程。
一些命令可以有多個(gè)DFO單元,因?yàn)槊總€(gè)DFO單元最多可以使用2個(gè)PX slaves set,如果一個(gè)命令有多個(gè)DFO單元,那么它就可以使用超過2個(gè)PX slaves set,可以在執(zhí)行計(jì)劃里看到是否使用了多個(gè)DFO單元:
select count() from (select /+ parallel(a 4) /count() from hash_t1 a
union
select /+ parallel(b 4) / count(*) from hash_t2 b)
行ID為6和12的行源兩處都有coordinator標(biāo)識(shí),這意味著這個(gè)命令使用了2個(gè)DFO單元。
通過SQL MONITORING也可以看到這個(gè)命令具有了2個(gè)并行組,理論上每個(gè)DFO單元之間可以同時(shí)進(jìn)行并行操作,但是我們這個(gè)例子里,兩個(gè)DFO單元之間的執(zhí)行順序是,先執(zhí)行DFO單元1,再執(zhí)行DFO單元2,可以通過【時(shí)間表】列看到,第一個(gè)DFO單元先活躍,等結(jié)束后,第二個(gè)DFO單元開始活躍。
從上圖還可以看出,DFO單元2復(fù)用了DFO單元1的并行進(jìn)程,沒有重新產(chǎn)生新的并行進(jìn)程,從并行進(jìn)程編號(hào)上可以看出這一點(diǎn)。SQL MONTIRONG是不是超級(jí)好用?
通過查詢v$pq_sesstat視圖,可以知道語(yǔ)句運(yùn)行時(shí)的DFO單元的數(shù)量(DFO Trees),并行集的個(gè)數(shù)(Slave Sets ),服務(wù)進(jìn)程的個(gè)數(shù)(Server Threads),執(zhí)行所采用的并行度(DOP)。如下:
寫到這里文章已經(jīng)有點(diǎn)長(zhǎng)了,對(duì)于12C的新特性還少有涉及,對(duì)于并行執(zhí)行傾斜的內(nèi)容也還未涉及,對(duì)于布隆過濾的傳遞和高級(jí)知識(shí)也未涉及。對(duì)于這些內(nèi)容,我會(huì)在下一篇進(jìn)行介紹。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。