PostgreSQL/GreenPlum Merge Inner Join解密

yzs87發表於2022-10-22

PostgreSQL/GreenPlum Merge Inner Join 解密

1、什麼是Merge Join

合併連線是一種匹配演算法,其中外表的每個記錄與內表的每個記錄進行匹配,直到存在連線子句匹配的可能性為止。 僅當兩個表都已排序並且 join子句的運算子是“=”時 ,才使用該演算法。

如下圖所示: merge join的位元組點需要Sort節點對內外表進行排序,然後進行join。

 

2、Merge Inner Join狀態機

狀態機如下圖所示:

EXEC_MJ_INITIALIZE_OUTER

該狀態是初始狀態,首先要從外表進行掃描。獲取外表記錄。根據外表掃描的記錄進行判斷:

1)  外表為空,即掃描出來的記錄為空,或者第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則結束join,返回NULL

2)  左表值為 NULL或者null排序後放在前面,則重新進入EXEC_MJ_INITIALIZE_OUTER狀態,掃描左表

3)  非上述兩種條件,則進入 EXEC_MJ_INITIALIZE_INNER狀態,獲取內表記錄

EXEC_MJ_INITIALIZE_INNER

該狀態下掃描內表。根據掃描的記錄進行判斷:

1)  內表為空,即掃描出來的記錄為空,或者 第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則結束join,返回NULL

2)  內表值為 NULL或者null排序後放在前面,則重新進入EXEC_MJ_INITIALIZE_INNER狀態,掃描右表

3)  非上述兩種條件,則進入 EXEC_MJ_SKIP_TEST狀態

EXEC_MJ_SKIP_TEST

該狀態需要對左右表值進行 join條件比較,根據比較結果判斷:

1)  = 右:標記內表排序後當前掃描位置;標記當前掃描的slot,進入EXEC_MJ_JOINTUPLES狀態

2)  < 右:進入EXEC_MJ_SKIPOUTER_ADVANCE狀態,掃描左表下一條記錄

3)  > 右:進入EXEC_MJ_SKIPINNER_ADVANCE狀態,掃描右表下一條記錄

EXEC_MJ_SKIPOUTER_ADVANCE

該狀態掃描外表下一條記錄。根據掃描的記錄進行判斷:

1)  外表掃描完,即掃描出來的記錄為空,或者第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則結束join,返回NULL

2)  左表值為 NULL或者null排序後放在前面,則重新進入EXEC_MJ_SKIPOUTER_ADVANCE狀態,掃描左表

3)  非上述兩種條件,則進入 EXEC_MJ_SKIP_TEST狀態,進行比較

EXEC_MJ_SKIPINNER_ADVANCE

該狀態掃描內表下一條記錄,根據掃描的記錄進行判斷:

1)  內表掃描完,即掃描出來的記錄為空,或者第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則結束join,返回NULL

2)  內表值為 NULL或者null排序後放在前面,則重新進入EXEC_MJ_SKIPINNER_ADVANCE狀態,掃描內表

3)  非上述兩種條件,則進入 EXEC_MJ_SKIP_TEST狀態,進行比較

因為左 > 右才會進入該狀態,右時一個NULL,那麼左表後面的值肯定也比右的前一個值大,所以join結束。

EXEC_MJ_JOINTUPLES

該狀態下,將左右表的值進行連線投影,輸出結果。下個週期呼叫 ExecMergeJoin函式時,直接進入EXEC_MJ_NEXTINNER狀態。

EXEC_MJ_NEXTINNER

該狀態下,掃描內表下一條記錄。並根據掃描的記錄進行判斷:

1)  內表掃描完,即掃描出來的記錄為空,或者第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則進入EXEC_MJ_NEXTOUTER狀態

2)  內表值為 NULL或者null排序後放在前面,則進入EXEC_MJ_NEXTOUTER狀態

3)  非上述兩種條件,進行比較,根據比較值進行操作:

= 右:進入EXEC_MJ_JOINTUPLES狀態

< 右:進入EXEC_MJ_NEXTOUTER狀態

不可能有左 > 右的分支,因為該狀態由 分支而來,排序都是由小到大,所以要麼相等,要麼右邊大

EXEC_MJ_NEXTOUTER

該狀態下獲取外表的下一條記錄,並根據值進行判斷:

1)  外表掃描完,即掃描出來的記錄為空,或者第一個 join條件的左表值為NULL並且null排序後放在最後且為inner join,則結束join,返回NULL

2)  左表值為 NULL或者null排序後放在前面,則重新進入EXEC_MJ_NEXTOUTER狀態,獲取外表下一條記錄

3)  非上述兩種條件,則進入 EXEC_MJ_JOINTUPLES狀態,否則進入EXEC_MJ_TESTOUTER狀態

EXEC_MJ_TESTOUTER

該狀態下,獲取標記的內表值,並與外表值比較

1)  = 右:需要標記內表排序的位置,並將當前slot放到mj_InnerTupleSlot中

2)  > 右:重新獲取右表當前掃描的位置的記錄

(1) 內表掃描完,或者內表記錄為 NULL並且第一個join條件並且null排在最後,結束join,返回NULL

(2) 內表記錄為 NULL,並且非第一個join條件或null排在前面,進入EXEC_MJ_SKIPINNER_ADVANCE狀態,獲取內表下一條記錄

(3) 非上述 2種情況,進入EXEC_MJ_SKIP_TEST狀態

不可能有左 < 右的分支,因為該狀態由 而來,排序都是由小到大,要麼相等,要麼左邊大。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31493717/viewspace-2919755/,如需轉載,請註明出處,否則將追究法律責任。

相關文章