時光荏苒,歲月如梭。樓主已經(jīng)很久沒有更新了。之前說好的一周一更的沒有做到。實在是事出有因,沒能靜下心來好好看代碼。當(dāng)然這不能作為我不更新的理由,時間擠擠還是有的,拖了這么久,該再寫點東西了,不然人就怠懶了。不過這回,我準(zhǔn)備寫的精簡些,一方面我想偷點懶省點時間,二來畢竟寫太長大家也不一定愛看。
之前我說過的查詢分析,查詢重寫和查詢規(guī)劃都是相當(dāng)于是對查詢的"編譯"。那么編譯完了就應(yīng)該按照既定的策略去執(zhí)行它。本篇就來介紹查詢執(zhí)行模塊的代碼(Executor),歡迎拍磚。
這部分我主要從以下五個部分介紹查詢執(zhí)行模塊(很可能要分成四到五篇文章來闡述,畢竟是比查詢規(guī)劃還要復(fù)雜的模塊):
1.查詢優(yōu)化策略 2.非可優(yōu)化語句的執(zhí)行 3.可優(yōu)化語句的執(zhí)行 4.計劃節(jié)點 5.其它子功能介紹
查詢執(zhí)行器的框架結(jié)構(gòu)如下圖所示。
在exec_simple_query函數(shù)中,調(diào)用查詢編譯模塊之后,就進(jìn)入了查詢執(zhí)行器模塊。在該模塊中,就是按照前一階段查詢規(guī)劃模塊鎖生成的查詢計劃,有機(jī)第調(diào)用存儲、索引,并發(fā)等模塊來完成數(shù)據(jù)的讀取或者修改的過程。
在本模塊中,總共下屬四個子模塊,分別是:Portal、ProcessUtility、Executor和其他特定子功能模塊。
我們知道,查詢規(guī)劃階段將查詢分為兩種類型,在查詢執(zhí)行模塊中,先由Portal模塊識別查詢類型(有計劃樹和無計劃樹),根據(jù)查詢類型分別指派Executor模塊和ProcessUtility模塊進(jìn)行處理。
這兩個子模塊的處理邏輯相差很大,執(zhí)行過程和先關(guān)數(shù)據(jù)結(jié)構(gòu)差異也很大。
對于Executor模塊,它根據(jù)輸入的查詢計劃樹按部就班地處理數(shù)據(jù)表中元組的增刪改查(DML)操作,它的執(zhí)行邏輯是統(tǒng)一的(所有的增刪改查最后都?xì)w結(jié)為SELECT,只是分別在SELECT的基礎(chǔ)上進(jìn)行一些額外的操作)。其主要代碼放在src/backend/executor下。
而對于ProcessUtility模塊,由于處理的是除了增刪改查之外的所有其他操作,而這些操作往往差異很大,例如數(shù)據(jù)定義操作(DDL),事務(wù)的處理以及游標(biāo)用戶角色定義這些,因此在ProcessUtility模塊中,為每種操作單獨(dú)地設(shè)計了子過程(函數(shù))去處理。主要代碼在src/backend/commands下。
而剩下的我說的特定功能子模塊,是指一些功能相對獨(dú)立和單一并且在整個查詢過程中會反復(fù)被調(diào)用的函數(shù)(我更愿意稱他們?yōu)楣ぞ吆瘮?shù)),例如各種輔助的子系統(tǒng),表達(dá)式的計算,投影運(yùn)算以及元組操作這些。
1.查詢優(yōu)化策略
在進(jìn)入這一模塊之前,我已經(jīng)簡要說明了Executor模塊和ProcessUtility模塊這兩個主要的執(zhí)行分支。這里要提到兩個概念:
可優(yōu)化語句和非可優(yōu)化語句
可優(yōu)化語句說白了就是DML語句,這些語句的特點就是都要查詢到滿足條件的元組。這類查詢都在查詢規(guī)劃階段生成了規(guī)劃樹,而規(guī)劃樹的生成過程中會根據(jù)查詢優(yōu)化理論進(jìn)行重寫和優(yōu)化以提高查詢速度,因此稱作可優(yōu)化語句。
那反過來講,那些沒有生成執(zhí)行計劃樹的功能性操作就是非可優(yōu)化語句了。這里只是提一下這個概念,在后面的介紹中會用。