上一篇我們介紹了查詢規(guī)劃模塊的總體流程和預(yù)處理部分的源碼。查詢規(guī)劃模塊再執(zhí)行完預(yù)處理之后,可以進(jìn)入正式的查詢規(guī)劃處理流程了。

查詢規(guī)劃的主要工作由grouping_planner函數(shù)完成。在具體實(shí)現(xiàn)的時(shí)候,針對postgresql中獨(dú)有的繼承表,程序使用inheritance_planner函數(shù)來解決,該函數(shù)主要是先將繼承表的繼承關(guān)系變換為非繼承表來處理,然后仍然調(diào)用的是grouping_planner函數(shù)來完成查詢規(guī)劃的工作。

因此,我們說查詢規(guī)劃的主要工作在于grouping_planner函數(shù)。本篇的重點(diǎn)也是來解析該函數(shù)內(nèi)部的調(diào)用關(guān)系和處理流程。



3.查詢規(guī)劃處理

這里大家真的要做好準(zhǔn)備,因?yàn)間rouping_planner函數(shù)本身就有將近1000行~

那什么,我們還是先上圖吧。有圖更清楚,文字太多大家也會暈的。以下是grouping_planner函數(shù)的流程圖。

grouping_planner函數(shù)是生成查詢計(jì)劃樹的主要函數(shù)。該函數(shù)首先要考慮查詢計(jì)劃中是否有集合操作(可通過查詢樹的setOperation變量來判斷)。如果有則需要進(jìn)行集合操作:遍歷setOperation,為其中的每一個(gè)子查詢生成計(jì)劃。而對于非集合操作,計(jì)劃的生成過程如下:

1) 如果查詢含有GROUP BY子句,那么就調(diào)整其GROUP BY屬性的順序以匹配ORDER BY子句中的屬性順序(如果使用了grouping sets,則需要做進(jìn)一步的變換,對于grouping sets,可以看這篇文章),這樣就可以使用一次排序操作同時(shí)實(shí)現(xiàn)排序和分組;

2) 調(diào)用preprocess_targetlist預(yù)處理INSERT、UPDATE、DELETE和FOR UPDATE情況下的目標(biāo)屬性;

3) 計(jì)算并確定代表排序需求的路徑關(guān)鍵字,按優(yōu)先級遞減排序主要有g(shù)roupClause、WindowClause,distinctClause和sortClause;

4) 調(diào)用query_planner函數(shù)為一個(gè)基本查詢創(chuàng)建路徑并獲得cheapest_path(代價(jià)最低執(zhí)行路徑),再調(diào)用get_cheape