【StoneDB Class】入門第五課:StoneDB 中的表連接


本次課程為大家講述 StoneDB 中的表連接。StoneDB 的表連接方式有 Nested Loop Join、Sort Merge Join、Map Join、Hash Join,不同的連接方式有不同的使用場(chǎng)景,在 StoneDB 中使用最廣泛的是 Map Join 和 Hash Join。下面為大家詳細(xì)介紹上述提到的四種表連接方式。

Nested Loop Join
通過(guò)一個(gè)示例來(lái)理解 Nested Loop Join 的原理:
假設(shè)優(yōu)化器會(huì)選擇表 t1 為驅(qū)動(dòng)表,表 t2 為被驅(qū)動(dòng)表,Nested Loop Join 的執(zhí)行過(guò)程如下:
1)遍歷驅(qū)動(dòng)表的結(jié)果集,取出結(jié)果集中的第1條記錄;
2)遍歷被驅(qū)動(dòng)表的結(jié)果集,按照關(guān)聯(lián)字段去判斷被驅(qū)動(dòng)表的結(jié)果集中是否存在匹配的記錄,如果匹配成功,則返回?cái)?shù)據(jù),否則就被丟棄;
3)直到遍歷完驅(qū)動(dòng)表的結(jié)果集為止。
從執(zhí)行過(guò)程可知,驅(qū)動(dòng)表有多少結(jié)果集,被驅(qū)動(dòng)表就需要掃描多少次。如果驅(qū)動(dòng)表的結(jié)果集很大,被驅(qū)動(dòng)表就要掃描很多次,SQL 的性能就會(huì)非常的差。在其它數(shù)據(jù)庫(kù)中,如果表連接方式是 Nested Loop Join,且被驅(qū)動(dòng)表的關(guān)聯(lián)字段是索引字段,那么 Nested Loop Join 還是很高效的。但在 StoneDB 中,即使表連接的關(guān)聯(lián)條件是等值查詢,且被驅(qū)動(dòng)表的關(guān)聯(lián)字段是索引字段,優(yōu)化器也不會(huì)選擇 Nested Loop Join,而選擇 Hash Join 或者 Map Join。
Nested Loop Join 的使用場(chǎng)景:多表關(guān)聯(lián)的連接字段是非等值查詢。
要想知道表與表之間進(jìn)行關(guān)聯(lián)使用的是哪種表連接方式,需要設(shè)置參數(shù) tianmu_control_trace,然后查看 trace.log,trace.log 的默認(rèn)保存路徑在 log 目錄下。


Sort Merge Join
通過(guò)一個(gè)示例來(lái)理解 Sort Merge Join 的原理:
向右滑動(dòng)代碼
在多表關(guān)聯(lián)返回較大數(shù)據(jù)量時(shí),Nested Loop Join 存在性能問(wèn)題,因此出現(xiàn)了 Sort Merge Join,Sort Merge Join 的執(zhí)行過(guò)程如下:
1)根據(jù)謂詞條件訪問(wèn)其中的一張表,得到的結(jié)果集按照表中的連接字段排序,排好序的結(jié)果集記為結(jié)果集 R1;
2)根據(jù)謂詞條件訪問(wèn)另外一張表,得到的結(jié)果集按照表中的連接字段排序,排好序的結(jié)果集記為結(jié)果集 R2;
3)遍歷結(jié)果集 R1,即取出結(jié)果集R1中的第1條記錄去和結(jié)果集 R2 中按照連接字段判斷是否存在匹配的記錄,直到遍歷完結(jié)果集 R1 中所有的記錄。
從執(zhí)行過(guò)程可知,Sort Merge Join 需要對(duì)連接字段進(jìn)行排序,我們知道在數(shù)據(jù)庫(kù)中做排序是比較消耗資源的,如果無(wú)法使用內(nèi)存排序,那么就需要使用磁盤排序,磁盤排序會(huì)生成臨時(shí)文件,導(dǎo)致大量 IO 和空間占用等問(wèn)題。在未出現(xiàn) Hash Join 之前,Sort Merge Join 是處理大數(shù)據(jù)較為理想的表連接方式。
Sort Merge Join 的使用場(chǎng)景:多表關(guān)聯(lián)的連接字段出現(xiàn)大于、小于比較。


Hash Join
通過(guò)一個(gè)示例來(lái)理解 Hash Join 的原理:
向右滑動(dòng)代碼
假設(shè)優(yōu)化器會(huì)選擇表 t2 為驅(qū)動(dòng)表,表 t3 為被驅(qū)動(dòng)表,Hash Join 的執(zhí)行過(guò)程如下:
1)在內(nèi)存中建立 hash table,根據(jù) hash 函數(shù)計(jì)算出表 t2 結(jié)果集中關(guān)聯(lián)字段的 hash value,將計(jì)算出的 hash value 存放到內(nèi)存的 hash table;
2)根據(jù) hash 函數(shù)計(jì)算出表 t3 結(jié)果集中關(guān)聯(lián)字段的 hash value;
3)表 t3 結(jié)果集中關(guān)聯(lián)字段的 hash value 與內(nèi)存中的 hash table 進(jìn)行匹配,如果匹配成功,則返回?cái)?shù)據(jù),否則就被丟棄。
從執(zhí)行過(guò)程可知,每張表只需要掃描一次,hash 函數(shù)可以把 hash value 均勻地打散,匹配的效率還是非常高效的。
Hash Join 的使用場(chǎng)景:多表關(guān)聯(lián)返回大量數(shù)據(jù),且連接字段必須是等值查詢。


Map Join
通過(guò)一個(gè)示例來(lái)理解 Map Join 的原理:
向右滑動(dòng)代碼
Map Join 的執(zhí)行過(guò)程與 Hash Join 的執(zhí)行過(guò)程很相似,通常情況下 Hash Join 算法比 Map Join 高效,如果把參數(shù) tianmu_force_hashjoin 打開,原本優(yōu)化器選擇的表連接方式是 Map Join,現(xiàn)在會(huì)選擇 Hash Join。?

以上是本次課程的全部?jī)?nèi)容,感謝各位繼續(xù)關(guān)注。如果您對(duì) StoneDB 感興趣,歡迎前往 StoneDB 代碼倉(cāng)庫(kù)了解更多,期待您的加入。
END