?
This document uses PHP Chinese website manual Release
執(zhí)行器(Theexecutor) 接受規(guī)劃器/優(yōu)化器傳過來的查詢規(guī)劃然后遞歸地處理它, 抽取所需要的行集合。它實際上是一個需求-拉動地流水線機制。 每次調用一個規(guī)劃節(jié)點地時候,它都必須給出更多的一個行,或者匯報它已經(jīng)完成行的傳遞了。
為了提供一個具體的例子,假設頂端節(jié)點是一個 MergeJoin 節(jié)點。 在做任何融合之前,首先得抓取兩行(每個子規(guī)劃一行)。 因此執(zhí)行器遞歸地調用自己來處理子規(guī)劃(它從附著在 lefttree 上的子規(guī)劃開始)。 新的頂端節(jié)點(左子規(guī)劃的頂端節(jié)點)假設是,一個 Sort 節(jié)點,然后還是需要遞歸地獲取一個輸入行。 Sort 節(jié)點的子節(jié)點可能是一個 SeqScan 節(jié)點,代表對一個表的實際讀取動作。 這個節(jié)點的執(zhí)行導致執(zhí)行器從表中抓取一行然后把它返回給調用的節(jié)點。 Sort 將不斷調用它的子節(jié)點以獲取需要排序的所有行。 在用盡輸入之后(由子節(jié)點返回一個 NULL 而不是一行表示),Sort 代碼執(zhí)行排序, 然后就可以返回它的第一個輸出行,也就是按照排序順序輸出的第一行。 它仍然保持剩下的行的排序狀態(tài),這樣在隨后有需求的時候,它就可以按照排序順序返回這些行。
MergeJoin節(jié)點也會類似地要求從它的右邊子規(guī)劃獲取第一行。 然后它比較這兩行看看它們是否能連接; 如果能,那么它給它的調用者返回一個連接行。 在下一次調用的時候,或者是在它無法連接當前的兩行的時候就是這次調用的時候, 它抓取其中一個表的下一行(抓取哪個表取決于比較結果如何), 然后再檢查看看兩個表是否匹配。最后,其中一個子規(guī)劃耗盡資源, 而MergeJoin返回 NULL ,表明無法繼續(xù)生成更多的連接行。
復雜的查詢可能包含許多層的規(guī)劃節(jié)點,但是一般的過程都是一樣的: 每個節(jié)點在每次被調用的時候都計算并返回它的下一個輸出行。 每個節(jié)點同樣負責附加上任何規(guī)劃器賦予它的選擇或者投影表達式。
執(zhí)行器機制是用于計算所有的四種基本 SQL 查詢類型的: SELECT,INSERT,UPDATE,DELETE。 對于SELECT而言,頂層的執(zhí)行器代碼只是需要發(fā)送查詢規(guī)劃樹返回的每一行給客戶端。 對于INSERT,返回的每一行都插入到 INSERT 聲明的目標表中。 This is done in a special top-level plan node calledModifyTable. 一個簡單的INSERT ... VALUES命令創(chuàng)建一個簡單的規(guī)劃樹,包含一個 Result 節(jié)點, 它只計算得出一個結果行。 但是INSERT ... SELECT可能需要執(zhí)行器的全部能力。 對于UPDATE,規(guī)劃器安排每個計算出來的行都包括所有更新的字段, 加上原來的目標行的 TID (行 ID); 執(zhí)行器的頂層使用這些信息創(chuàng)建一個新的更新過的行,并且標記舊行被刪除。 對于 ForDELETE,規(guī)劃實際上返回的唯一的一個字段是 TID , 然后執(zhí)行器的頂層簡單地使用這個 TID 訪問每個目標行,并且把它們標記為已刪除。