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