如何理解GaussDB explain分布式執(zhí)行計(jì)劃,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、網(wǎng)站空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、榆林網(wǎng)站維護(hù)、網(wǎng)站推廣。
執(zhí)行計(jì)劃(又稱解釋計(jì)劃)是數(shù)據(jù)庫(kù)執(zhí)行SQL語(yǔ)句的具體步驟,例如通過(guò)索引還是全表掃描訪問(wèn)表中的數(shù)據(jù),連接查詢的實(shí)現(xiàn)方式和連接的順序等。如果 SQL 語(yǔ)句性能不夠理想,我們首先應(yīng)該查看它的執(zhí)行計(jì)劃。本文主要介紹如何詳細(xì)解讀GaussDB(DWS)產(chǎn)生的分布式執(zhí)行計(jì)劃,從計(jì)劃中發(fā)現(xiàn)性能調(diào)優(yōu)點(diǎn)。
要讀懂執(zhí)行計(jì)劃,首先要知道數(shù)據(jù)庫(kù)執(zhí)行算子的概念:
下面重點(diǎn)介紹下基于sharing nothing的分布式計(jì)劃中最重要的一類算子——STREAM算子
三種類型的stream算子
1) Gather Stream (N:1) – 每個(gè)源結(jié)點(diǎn)都將其數(shù)據(jù)發(fā)送給目標(biāo)結(jié)點(diǎn)
2) redistribute Stream (N:N) – 每個(gè)源節(jié)點(diǎn)將其數(shù)據(jù)根據(jù)連接條件計(jì)算Hash值,根據(jù)重新計(jì)算的Hash值進(jìn)行分布,發(fā)給對(duì)應(yīng)的目標(biāo)節(jié)點(diǎn)
3) Broadcast Stream (1:N) – 由一個(gè)源節(jié)點(diǎn)將其數(shù)據(jù)發(fā)給N個(gè)目標(biāo)節(jié)點(diǎn)
其中1)主要用于CN與DN間的數(shù)據(jù)交換,2)與3)主要用于DN間的數(shù)據(jù)交換
SQL執(zhí)行計(jì)劃是一個(gè)節(jié)點(diǎn)數(shù),顯示執(zhí)一條SQL語(yǔ)句執(zhí)行時(shí)的詳細(xì)步驟。每一個(gè)步驟是一個(gè)數(shù)據(jù)庫(kù)運(yùn)算符,也叫作一個(gè)執(zhí)行算子。使用explain命令可以查看優(yōu)化器為每個(gè)查詢生成的具體執(zhí)行計(jì)劃。
1) EXPLAIN的語(yǔ)法
其中,option中COSTS與NODES的默認(rèn)值為ON,其他參數(shù)默認(rèn)為OFF。
說(shuō)明:
a) EXPLAIN + QUERY并不會(huì)真正執(zhí)行,只會(huì)將計(jì)劃打印出來(lái),指定option中的ANALYZE可以進(jìn)行實(shí)際執(zhí)行
b) PERFORMANCE 選項(xiàng)默認(rèn)會(huì)將所有的選項(xiàng)置為ON,即顯示所有的執(zhí)行信息。
c) CPU/BUFFER/DETAIL 選項(xiàng)依賴于ANALYZE,只有ANALYZE置為ON的時(shí)候,才能使用這幾個(gè)選項(xiàng)。
d) DETAIL選項(xiàng)用來(lái)控制輸出,DETAIL 置為ON時(shí),會(huì)顯示各個(gè)DN上具體的執(zhí)行信息;DATAIL 置為OFF時(shí),顯示所有DN的匯總信息,即最大最小值信息。
2) EXPLAIN顯示格式
GaussDB中提供了兩種顯示格式(normal/pretty),通過(guò)設(shè)置參數(shù)explain_perf_mode進(jìn)行控制。其中,normal格式為默認(rèn)的顯示格式。
normal格式如下:
pretty格式如下:
改進(jìn)后的顯示格式,層次清晰,計(jì)劃包含了plan node id,性能分析會(huì)更加簡(jiǎn)單直接。
使用之前可以使用show explain_perf_mode;來(lái)查看當(dāng)前數(shù)據(jù)庫(kù)使用的顯示風(fēng)格。
同時(shí)可以使用set explain_perf_mode=pretty/normal;來(lái)設(shè)置輸出的格式。
1) 四中常見(jiàn)類型計(jì)劃
建表語(yǔ)句:
a) FQS計(jì)劃,完全下推,下發(fā)query
兩表JOIN,且其連接條件為各表的分布列,在關(guān)閉stream算子的情況下,CN會(huì)直接將該語(yǔ)句發(fā)送至各DN執(zhí)行,最后結(jié)果在CN匯總。
b) 非FQS計(jì)劃,部分語(yǔ)句下推
兩表JOIN,且連接條件中包含非分布列,此時(shí)在關(guān)閉stream算子的情況下,CN會(huì)將基表掃描語(yǔ)句下發(fā)至各DN,然后在CN上進(jìn)行JOIN。
c) Stream計(jì)劃,DN之間無(wú)數(shù)據(jù)交換
兩表JOIN,且連接條件為各表的分布列,因此各DN無(wú)需數(shù)據(jù)交換。CN生成stream計(jì)劃后,將除Gather Stream的計(jì)劃下發(fā)給DN執(zhí)行,在各個(gè)DN上進(jìn)行基表 掃描,并進(jìn)行哈希連接后,發(fā)送給CN。
d) Stream計(jì)劃,DN之間存在數(shù)據(jù)交換
兩表JOIN,且連接條件包含非分布列,在開(kāi)啟stream算子的情況下,會(huì)生成stream計(jì)劃,其DN間存在數(shù)據(jù)交換。此時(shí)對(duì)于tt02表,會(huì)在各DN進(jìn)行基表掃描,掃描后會(huì)通過(guò)Redistribute Stream算子,按照J(rèn)OIN條件中的tt02.c1進(jìn)行哈希計(jì)算后重新發(fā)送給各DN,然后在各DN上做JOIN,最后匯總到CN。
2) explain performance詳解
a) 執(zhí)行計(jì)劃
?id:執(zhí)行算子節(jié)點(diǎn)編號(hào)。
?operation:具體的執(zhí)行節(jié)點(diǎn)算子名稱。
?A-time:各DN相應(yīng)算子執(zhí)行時(shí)間,[]中左側(cè)為最小值,右側(cè)為最大值,包括下層算子執(zhí)行時(shí)間。
?A-rows:相應(yīng)算子輸出的全局總行數(shù)。
?E-rows:每個(gè)算子估算的輸出行數(shù)。
?Peak Memory:各DN相應(yīng)算子消耗內(nèi)存峰值,[]中左側(cè)為最小值,右側(cè)為最大值。
?E-memory:DN上每個(gè)算子估算的內(nèi)存使用量,只有DN上執(zhí)行的算子會(huì)顯示。某些場(chǎng)景會(huì)在估算的內(nèi)存使用量后使用括號(hào)顯示該算子在內(nèi)存源充足下可以自動(dòng)擴(kuò)展的內(nèi)存上限。
?E-width:每個(gè)算子輸出元組的估算寬度。
?E-costs:每個(gè)算子估算的執(zhí)行代價(jià)。
b) 謂詞過(guò)濾
顯示對(duì)應(yīng)執(zhí)行算子節(jié)點(diǎn)的過(guò)濾條件
c) 內(nèi)存使用
主要顯示CN的最大內(nèi)存用量、DN最大內(nèi)存用量、各算子的最大內(nèi)存用量、各算子預(yù)估內(nèi)存用量、Stream線程的啟動(dòng)以及收發(fā)時(shí)間。
d) Targetlist Information
各個(gè)算子對(duì)應(yīng)的輸出目標(biāo)列信息。
e) DN信息
各算子的執(zhí)行時(shí)間、Buffer、CPU信息
f) 自定義信息
CN與DN之間的建連信息、DN與DN之間的建連信息。
g) 匯總信息
DN執(zhí)行器開(kāi)始時(shí)間,[min_node_name, max_node_name] : [min_time, max_time]
DN執(zhí)行器結(jié)束時(shí)間,[min_node_name, max_node_name] : [min_time, max_time]
Remote query poll time:接收結(jié)果時(shí)用于poll等待的時(shí)間
CN執(zhí)行器開(kāi)始、運(yùn)行及結(jié)束時(shí)間
網(wǎng)絡(luò)流量,stream算子發(fā)送的數(shù)據(jù)量
優(yōu)化器執(zhí)行期時(shí)間
查詢ID
總執(zhí)行時(shí)間
h) 執(zhí)行時(shí)間介紹
每個(gè)算子的執(zhí)行信息都包含三個(gè)部分:
其中:
dn_6001_6002/dn_6003_6004 表示具體執(zhí)行的節(jié)點(diǎn)信息,括號(hào)中的信息是實(shí)際的執(zhí)行信息
actual time=0.013..2290.971 表示實(shí)際的執(zhí)行時(shí)間
第一個(gè)數(shù)字表示執(zhí)行時(shí)進(jìn)入當(dāng)前算子到輸出第一條數(shù)據(jù)所花費(fèi)的時(shí)間
第二個(gè)數(shù)字為輸出所有數(shù)據(jù)的總執(zhí)行時(shí)間
注意:在整個(gè)計(jì)劃中,除了葉子節(jié)點(diǎn)的執(zhí)行時(shí)間是算子本身的執(zhí)行時(shí)間,其余算子的執(zhí)行時(shí)間均包含子節(jié)點(diǎn)的執(zhí)行時(shí)間。
在該計(jì)劃中,7號(hào)節(jié)點(diǎn)和9號(hào)節(jié)點(diǎn)為葉子節(jié)點(diǎn),其余節(jié)點(diǎn)均為非葉子簡(jiǎn)介。1號(hào)節(jié)點(diǎn)時(shí)頂層節(jié)點(diǎn),所以該節(jié)點(diǎn)的執(zhí)行時(shí)間就可以作為整個(gè)查詢的執(zhí)行時(shí)間。
rows=2001550 表示當(dāng)前算子輸出數(shù)據(jù)為2001550行;
loops=1 表示當(dāng)前算子的只執(zhí)行了一次,而對(duì)于分區(qū)表的掃描(7號(hào)節(jié)點(diǎn))來(lái)說(shuō):
該層掃描算子的loops為7,對(duì)于分區(qū)表,每一個(gè)分區(qū)表的掃描就是一次完整的掃描操作,當(dāng)切換到下一個(gè)分區(qū)的時(shí)候,又是一次新的查詢操作,查詢?cè)摫矶x如下:
Inventory表有7個(gè)分區(qū),所以就執(zhí)行了7次表掃描操作,因此loops=7。
i) CPU信息介紹
每個(gè)算子執(zhí)行的過(guò)程都有CPU信息,其中cyc代表的是CPU的周期數(shù),ex cyc表示的是當(dāng)前算子的周期數(shù),不包含其子節(jié)點(diǎn);inc cyc是包含子節(jié)點(diǎn)的周期數(shù);ex row是當(dāng)前算子輸出的數(shù)據(jù)行數(shù);ex c/r則是ex cyc/ex row得到的每條數(shù)據(jù)所用的平均周期數(shù)。
j) Buffer信息介紹
buffers顯示緩沖區(qū)信息,包括共享塊和臨時(shí)塊的讀和寫(xiě)。
共享塊包含表和索引,臨時(shí)塊在排序和物化中使用的磁盤塊。上層節(jié)點(diǎn)顯示出來(lái)的塊數(shù)據(jù)包含了其所有子節(jié)點(diǎn)使用的塊數(shù)。
Buffers涉及的參數(shù)有兩種,分別為:shared和temp,及shared hit/read/dirtied/written以及temp read/write
Hit blocks:代表從磁盤里面讀到的數(shù)據(jù)塊數(shù)
Dirtied blocks:代表當(dāng)前查詢中被修改了的并且此前未被修改的數(shù)據(jù)塊數(shù)
Written blocks:代表當(dāng)前線程將shared bufer里被修改的數(shù)據(jù)寫(xiě)回到磁盤的塊數(shù)
k) 執(zhí)行內(nèi)存
其中:
Peak Memory:5KB 表示當(dāng)前算子實(shí)際執(zhí)行時(shí)使用的峰值內(nèi)存;
Estimate Memory:1024MB 表示預(yù)估的內(nèi)存,為優(yōu)化器給出的預(yù)估值。
l) 其他執(zhí)行信息
(1)sort 算子,會(huì)顯示排序信息
Sort Method代表排序的方法,包括quicksort(快排)和disksort(外排)。快排即內(nèi)存夠用時(shí),所有的排序操作均在內(nèi)存中完成,外排說(shuō)明當(dāng)前可用內(nèi)存不足,需要下盤。
(2)hashjoin算子
Buckets:代表hash表中實(shí)際使用的桶的個(gè)數(shù)
Batches:代表hashjoin中實(shí)際分塊的數(shù)量。如果Batches=1,則說(shuō)明所有的數(shù)據(jù)全在內(nèi)存中,沒(méi)有下盤操作;反之則說(shuō)明有下盤操作,Batches - 1代表臨時(shí)文件的個(gè)數(shù)。
Memory Usage:就是hashjoin中內(nèi)存的使用情況
(3)hashagg算子
如果發(fā)生數(shù)據(jù)下盤,會(huì)有File Num:512信息,顯示臨時(shí)文件的個(gè)數(shù)。
(4)stream算子
stream算子的會(huì)統(tǒng)計(jì)當(dāng)前算子處理數(shù)據(jù)的字節(jié)數(shù),其從子線程獲取數(shù)據(jù)的時(shí)間(poll time)以及處理數(shù)據(jù)的時(shí)間(Deserialize Time)。
stream算子的子節(jié)點(diǎn)會(huì)統(tǒng)計(jì)發(fā)送端的時(shí)間信息,如下:
發(fā)送時(shí)間Send time,排隊(duì)時(shí)間Wait Quota time, OS發(fā)送時(shí)間以及數(shù)據(jù)處理的時(shí)間。
3) explain 調(diào)優(yōu)示例
一個(gè)查詢語(yǔ)句要經(jīng)過(guò)多個(gè)算子步驟才會(huì)輸出最終的結(jié)果。由于個(gè)別算子耗時(shí)過(guò)長(zhǎng)導(dǎo)致整體查詢性能下降的情況比較常見(jiàn)。這些算子是整個(gè)查詢的瓶頸算子。通用的優(yōu)化手段是EXPLAIN ANALYZE/PERFORMANCE命令查看執(zhí)行過(guò)程的瓶頸算子,然后進(jìn)行針對(duì)性優(yōu)化。
基表掃描時(shí),對(duì)于點(diǎn)查或者范圍掃描等過(guò)濾大量數(shù)據(jù)的查詢,如果使用SeqScan全表掃描會(huì)比較耗時(shí),可以在條件列上建立索引選擇IndexScan進(jìn)行索引掃描提升掃描效率。如下示例:
上述例子中,全表掃描返回3360條數(shù)據(jù),過(guò)濾掉大量數(shù)據(jù),在sssolddate_sk列上建立索引后,使用IndexScan掃描效率顯著提高,從960毫秒提升到8毫秒。
關(guān)于如何理解GaussDB explain分布式執(zhí)行計(jì)劃問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。