重慶分公司,新征程啟航
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
一般來(lái)說(shuō),閱讀執(zhí)行計(jì)劃通常采用自底往上的方法,這好比從樹(shù)的某片葉子出發(fā)然后再到樹(shù)枝再到樹(shù)干、樹(shù)根這么一種方法來(lái)了解一顆樹(shù),這種方法存在的問(wèn)題是如果這顆樹(shù)很大,那么就可能出現(xiàn)“只見(jiàn)葉子不見(jiàn)樹(shù)干”難以把握整體的情況。這時(shí)候可以結(jié)合自頂往下的方法進(jìn)行閱讀,從而在整體把握整個(gè)執(zhí)行計(jì)劃。
成都創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)的成都網(wǎng)站建設(shè)公司,我們專(zhuān)注網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷(xiāo)、企業(yè)網(wǎng)站建設(shè),賣(mài)友情鏈接,廣告投放為企業(yè)客戶(hù)提供一站式建站解決方案,能帶給客戶(hù)新的互聯(lián)網(wǎng)理念。從網(wǎng)站結(jié)構(gòu)的規(guī)劃UI設(shè)計(jì)到用戶(hù)體驗(yàn)提高,創(chuàng)新互聯(lián)力求做到盡善盡美。
為了更好的理解和使用自頂往下的閱讀方法,需要預(yù)先掌握一些基礎(chǔ)知識(shí).
計(jì)劃節(jié)點(diǎn)類(lèi)型
在PostgreSQL中,計(jì)劃節(jié)點(diǎn)分為四類(lèi),分別是控制節(jié)點(diǎn)(Control Node)、掃描節(jié)點(diǎn)(ScanNode),物化節(jié)點(diǎn)(Materialization Node)、連接節(jié)點(diǎn)(Join Node) 。
1.控制節(jié)點(diǎn):是一類(lèi)用于處理特殊情況的節(jié)點(diǎn),用于實(shí)現(xiàn)特殊的執(zhí)行流程。例如,Result節(jié)點(diǎn)可用來(lái)表示INSERT語(yǔ)句中VALUES子句指定的將要插人的元組。
2.掃描節(jié)點(diǎn):此類(lèi)節(jié)點(diǎn)用于掃描表等對(duì)象以從中獲取元組。例如,SeqScan節(jié)點(diǎn)用于順序掃描一個(gè)表.毎次掃描一個(gè)元組。
3.物化節(jié)點(diǎn):這類(lèi)節(jié)點(diǎn)種類(lèi)比較復(fù)雜,但它們有一個(gè)共同特點(diǎn),即能夠緩存執(zhí)行結(jié)果到輔助存儲(chǔ)中。物化節(jié)點(diǎn)會(huì)在第一次被執(zhí)行時(shí)生成其中的所有結(jié)果元組,然后將這些結(jié)果元組緩存起來(lái),等待其上層節(jié)點(diǎn)取用;而非物化節(jié)點(diǎn)則是每次被執(zhí)行時(shí)生成一個(gè)結(jié)果元組并返回給上層節(jié)點(diǎn)。例如,Sort節(jié)點(diǎn)能夠獲取下層節(jié)點(diǎn)返回的所有元組并根據(jù)指定的屬性進(jìn)行排序,并將排序結(jié)果全部緩存起來(lái),每次上層節(jié)點(diǎn)從Sort節(jié)點(diǎn)取元組時(shí)就從緩存中按順序返回下一個(gè)元組。
4.連接節(jié)點(diǎn):此類(lèi)節(jié)點(diǎn)對(duì)應(yīng)于關(guān)系代數(shù)中的連接操作,可以實(shí)現(xiàn)多種連接方式(條件連接、左連接、右連接、全連接、自然連接等),每種節(jié)點(diǎn)實(shí)現(xiàn)一種連接算法。例如,HashJoin實(shí)現(xiàn)了基于Hash的連接箅法。
為了方便起見(jiàn),在此基礎(chǔ)上進(jìn)行推廣,設(shè)置規(guī)則:如控制節(jié)點(diǎn)/物化節(jié)點(diǎn)的子節(jié)點(diǎn)為連接節(jié)點(diǎn),則視為連接節(jié)點(diǎn),否則視為非連接節(jié)點(diǎn).
根據(jù)這條規(guī)則,可以把所有的節(jié)點(diǎn)分為兩類(lèi),即連接節(jié)點(diǎn)和非連接節(jié)點(diǎn).
自頂往下的方法,顧名思義,從執(zhí)行計(jì)劃的最頂端/最外層進(jìn)行閱讀.
1.識(shí)別節(jié)點(diǎn)類(lèi)型(非連接節(jié)點(diǎn) vs 連接節(jié)點(diǎn))
2.如為非連接節(jié)點(diǎn),則識(shí)別該節(jié)點(diǎn)的具體類(lèi)型(數(shù)據(jù)表掃描...),該分支結(jié)束
3.如為連接節(jié)點(diǎn),則識(shí)別連接的outer端和inner端
3.1 對(duì)outer端遞歸應(yīng)用1/2/3步驟
3.2 對(duì)inner端遞歸應(yīng)用1/2/3步驟
下面舉例說(shuō)明,SQL腳本如下:
testdb=# explain verbose select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je
testdb-# from t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny,jf.je
testdb(# from t_grxx gr inner join t_jfxx jf
testdb(# on gr.dwbh = dw.dwbh
testdb(# and gr.grbh = jf.grbh) grjf
testdb-# where dw.dwbh in ('1001','1002')
testdb-# order by dw.dwbh;
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.87..61.01 rows=20 width=47)
Output: dw.dwmc, dw.dwbh, dw.dwdz, gr.grbh, gr.xm, jf.ny, jf.je
-> Nested Loop (cost=0.58..53.88 rows=20 width=32)
Output: dw.dwmc, dw.dwbh, dw.dwdz, gr.grbh, gr.xm
-> Index Scan using t_dwxx_pkey on public.t_dwxx dw (cost=0.29..13.92 rows=2 width=20)
Output: dw.dwmc, dw.dwbh, dw.dwdz
Index Cond: ((dw.dwbh)::text = ANY ('{1001,1002}'::text[]))
-> Index Scan using idx_t_grxx_dwbh on public.t_grxx gr (cost=0.29..19.88 rows=10 width=16)
Output: gr.dwbh, gr.grbh, gr.xm, gr.xb, gr.nl
Index Cond: ((gr.dwbh)::text = (dw.dwbh)::text)
-> Index Scan using idx_t_jfxx_grbh on public.t_jfxx jf (cost=0.29..0.35 rows=1 width=20)
Output: jf.grbh, jf.ny, jf.je
Index Cond: ((jf.grbh)::text = (gr.grbh)::text)
(13 rows)
1.識(shí)別節(jié)點(diǎn)類(lèi)型: Nested Loop -> 連接節(jié)點(diǎn)
3.連接節(jié)點(diǎn):識(shí)別outer端,即通常所說(shuō)的驅(qū)動(dòng)表(這里是Nested Loop)和inner端(Index Scan).
3.1 outer端為連接節(jié)點(diǎn),類(lèi)型為Nested Loop
遞歸應(yīng)用1/2/3步驟,解析該Nested Loop
3.1.1 outer端為Index Scan on t_dwxx
3.1.2 inner端為Index Scan on t_grxx
3.2 inner端,遞歸應(yīng)用1/2/3步驟,即Index Scan on t_jfxx
采用自頂往下的方法,可以從"大局"上對(duì)執(zhí)行計(jì)劃上進(jìn)行把握,避免一開(kāi)始就進(jìn)入繁雜的細(xì)節(jié)之中.
PgSQL · 最佳實(shí)踐 · EXPLAIN 使用淺析
跟我一起讀postgresql源碼(九)