上一篇我們介紹了查詢規(guī)劃模塊的總體流程和預處理部分的源碼。查詢規(guī)劃模塊再執(zhí)行完預處理之后,可以進入正式的查詢規(guī)劃處理流程了。
查詢規(guī)劃的主要工作由grouping_planner函數(shù)完成。在具體實現(xiàn)的時候,針對postgresql中獨有的繼承表,程序使用inheritance_planner函數(shù)來解決,該函數(shù)主要是先將繼承表的繼承關(guān)系變換為非繼承表來處理,然后仍然調(diào)用的是grouping_planner函數(shù)來完成查詢規(guī)劃的工作。
因此,我們說查詢規(guī)劃的主要工作在于grouping_planner函數(shù)。本篇的重點也是來解析該函數(shù)內(nèi)部的調(diào)用關(guān)系和處理流程。
3.查詢規(guī)劃處理
這里大家真的要做好準備,因為grouping_planner函數(shù)本身就有將近1000行~
那什么,我們還是先上圖吧。有圖更清楚,文字太多大家也會暈的。以下是grouping_planner函數(shù)的流程圖。
grouping_planner函數(shù)是生成查詢計劃樹的主要函數(shù)。該函數(shù)首先要考慮查詢計劃中是否有集合操作(可通過查詢樹的setOperation變量來判斷)。如果有則需要進行集合操作:遍歷setOperation,為其中的每一個子查詢生成計劃。而對于非集合操作,計劃的生成過程如下:
1) 如果查詢含有GROUP BY子句,那么就調(diào)整其GROUP BY屬性的順序以匹配ORDER BY子句中的屬性順序(如果使用了grouping sets,則需要做進一步的變換,對于grouping sets,可以看這篇文章),這樣就可以使用一次排序操作同時實現(xiàn)排序和分組;
2) 調(diào)用preprocess_targetlist預處理INSERT、UPDATE、DELETE和FOR UPDATE情況下的目標屬性;
3) 計算并確定代表排序需求的路徑關(guān)鍵字,按優(yōu)先級遞減排序主要有g(shù)roupClause、WindowClause,distinctClause和sortClause;
4) 調(diào)用query_planner函數(shù)為一個基本查詢創(chuàng)建路徑并獲得cheapest_path(代價最低執(zhí)行路徑),再調(diào)用get_cheape