40.6. 執行器

執行器接受規劃器/優化器傳過來地查詢規劃然後遞歸地處理它, 抽取所需要地行集合。它實際上是一個需求-拉動地流水線機制。 每次調用一個規劃節點地時候,它都必須給出更多的一個行,或者匯報它已經完成行的傳遞了。

為了提供一個紮實的例子,假設頂端節點是一個 MergeJoin 節點。 在做任何融合之前,首先得抓取兩行(每個自規劃一行)。因此執行器遞歸地調用自己來處理資規劃(它從附著在 lefttree上的資規劃開始)。新的頂端節點(左子規劃的頂端節點)假設是,一個 Sort 節點, 然後還是需要遞歸地獲取一個輸入行。Sort 節點的子節點可能是一個 SeqScan 節點,代資料表對一個資料表的實際讀取動作。 這個節點的執行導致執行器從資料表中抓取一行然後把它返回給調用的節點。 Sort 將不斷調用它的子節點以獲取需要排序的所有行。 在用盡輸入之後(由子節點返回一個 NULL 而不是一行資料表示),Sort 代碼執行排序,然後就可以返回它的第一個輸出行,也就是按照排序順序輸出的第一行。 它仍然保持剩下的行的排序狀態,這樣在隨後有需求的時候,它就可以按照排序順序返回這些行。

MergeJoin 節點也會類似地要求從它的右邊子規劃獲取第一行。 然後它比較這兩行看看它們是否能連接;如果能,那麼它給它的調用者返回一個連接行。 在下一次調用的時候,或者是在它無法連接目前的兩行的時候就是這次調用的時候, 它抓取其中一個資料表的下一行(抓取哪個資料表取決於比較結果如何),然後再檢查看看兩個資料表是否匹配。 最後,其中一個子規劃耗盡資源,而 MergeJoin 返回 NULL,資料表明無法繼續生成更多的連接行。

複雜的查詢可能包含許多層的規劃節點,但是一般的過程都是一樣的: 每個節點再每次被調用的時候都計算並返回它的下一個輸出行。 每個節點同樣負責附加上任何規劃器賦予它的選擇或者投影資料表達式。

執行器機制是用於計算所有的四種基本 SQL 查詢類型的: SELECTINSERTUPDATE, 和 DELETE。對於 SELECT 而言,頂層的執行器代碼只是需要發送查詢規劃樹返回的每一行給客戶端。 對於 INSERT,返回的每一行都插入到 INSERT 聲明的目標資料表中。 (一個簡單的 INSERT ... VALUES 命令建立一個簡單的規劃樹,包含一個 Result 節點,它只計算得出一個結果行。 但是 INSERT ... SELECT 可能需要執行器的全部能力。) 對於 UPDATE,規劃器安排每個計算出來的行都包括所有更新的字串,加上原來的目標行的 TID (資料 ID,或者行 ID); 執行器的頂層使用這些訊息建立一個新的更新過的行,並且標記舊行被刪除。對於 DELETE, 規劃實際上返回的唯一的一個字串是 TID,然後執行器的頂層簡單地使用這個 TID 訪問每個目標行,並且把它們標記為已刪除。