Apache?Doris?Join?優(yōu)化原理詳解
背景 & 目標(biāo)
掌握 Apache Doris Join 優(yōu)化手段及其實(shí)現(xiàn)原理為代碼閱讀提供理論基礎(chǔ)Doris 數(shù)據(jù)劃分
不同的加入方式取決于對(duì)Doris中數(shù)據(jù)分區(qū)的透徹理解。所以這里先列出必要的基礎(chǔ)知識(shí)。
首先,在Doris中,數(shù)據(jù)是以表格的形式進(jìn)行邏輯描述的。
在Doris的存儲(chǔ)引擎中,用戶數(shù)據(jù)被橫向劃分為若干個(gè)數(shù)據(jù)片(也稱為數(shù)據(jù)桶)。每個(gè)數(shù)位板包含幾個(gè)數(shù)據(jù)行。各個(gè)平板的數(shù)據(jù)之間沒有交集,物理上獨(dú)立存儲(chǔ)。
一個(gè)平板電腦只屬于一個(gè)數(shù)據(jù)分區(qū)。一個(gè)分區(qū)包含幾個(gè)平板電腦。因?yàn)槠桨咫娔X是物理獨(dú)立存放的,所以可以認(rèn)為隔板也是物理獨(dú)立的。平板電腦是數(shù)據(jù)移動(dòng)、復(fù)制和其他操作的最小物理存儲(chǔ)單元。
幾塊隔板組成一張桌子。分區(qū)可以被視為最小的邏輯管理單元。只能對(duì)一個(gè)分區(qū)進(jìn)行數(shù)據(jù)的導(dǎo)入和刪除。
Doris支持兩層數(shù)據(jù)分區(qū)。第一層是Partition,支持范圍和列表的劃分。第二層是Bucket(Tablet),只支持哈希分區(qū)。您也可以只使用一層分區(qū)。當(dāng)使用一層分區(qū)時(shí),僅支持桶分區(qū)。
解釋下圖中桌子、分區(qū)和桶(平板電腦)之間的關(guān)系:
Table 按照 Range 的方式按照 date 字段進(jìn)行分區(qū),得到了 N 個(gè) Partition每個(gè) Partition 通過相同的 Hash 方式將其中的數(shù)據(jù)劃分為 M 個(gè) Bucket(Tablet)從邏輯上來說,Bucket 1 可以包含 N 個(gè) Partition 中劃分得到的數(shù)據(jù),比如下圖中的 Tablet 11、Tablet 21、Tablet N1特別注意:
Doris中分區(qū)和桶的定義可能與其他一些數(shù)據(jù)庫系統(tǒng)不同。下面是一個(gè)特定的表構(gòu)建語句作為示例:
CREATE TABLE IF NOT EXISTS example_db.expamle_range_tbl( `user_id` LARGEINT NOT NULL COMMENT "用戶id", `date` DATE NOT NULL COMMENT "數(shù)據(jù)灌入日期時(shí)間", `timestamp` DATETIME NOT NULL COMMENT "數(shù)據(jù)灌入的時(shí)間戳", `city` VARCHAR(20) COMMENT "用戶所在城市", `age` SMALLINT COMMENT "用戶年齡", `sex` TINYINT COMMENT "用戶性別", `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用戶最后一次訪問時(shí)間", `cost` BIGINT SUM DEFAULT "0" COMMENT "用戶總消費(fèi)", `max_dwell_time` INT MAX DEFAULT "0" COMMENT "用戶最大停留時(shí)間", `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用戶最小停留時(shí)間")ENGINE=OLAPAGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`)PARTITION BY RANGE(`date`)( PARTITION `p201701` VALUES LESS THAN ("2017-02-01"), PARTITION `p201702` VALUES LESS THAN ("2017-03-01"), PARTITION `p201703` VALUES LESS THAN ("2017-04-01"))DISTRIBUTED BY HASH(`user_id`) BUCKETS 16PROPERTIES( "replication_num" = "3");綠色:分區(qū),在本例中,日期字段用于分區(qū)。
藍(lán)色突出顯示:Bucket,在本例中,user_id字段用作分發(fā)列表。
劃分
Partition 列可以指定一列或多列,分區(qū)列必須為 KEY 列分區(qū)數(shù)量理論上沒有上限當(dāng)不使用 Partition 建表時(shí),系統(tǒng)會(huì)自動(dòng)生成一個(gè)和表名同名的,全值范圍的 Partition。該 Partition 對(duì)用戶不可見,并且不可刪改創(chuàng)建分區(qū)時(shí),不能添加具有重疊范圍的分區(qū)。
有兩種分區(qū)方式:
分區(qū)方式一般用法Range通常按時(shí)間分區(qū),以方便地管理新舊數(shù)據(jù)List支持的類型更豐富,分區(qū)值為枚舉值。只有當(dāng)數(shù)據(jù)為目標(biāo)分區(qū)枚舉值其中之一時(shí),才可以命中分區(qū)水桶
如果使用了 Partition,則 DISTRIBUTED 語句描述的是數(shù)據(jù)在各個(gè)分區(qū)內(nèi)的劃分規(guī)則。如果不使用 Partition,則描述的是對(duì)整個(gè)表的數(shù)據(jù)劃分規(guī)則分桶列的選擇,是在 查詢吞吐 和 查詢并發(fā) 之間的一種權(quán)衡:如果選擇多個(gè)分桶列,則數(shù)據(jù)分布更均勻。如果一個(gè)查詢條件不包含所有分桶列的等值條件(意味著無法做桶裁剪以減少數(shù)據(jù)查詢范圍),那么該查詢會(huì)觸發(fā)所有分桶同時(shí)掃描,這樣查詢的吞吐會(huì)增加,單個(gè)查詢的延遲隨之降低。這個(gè)方式適合大吞吐低并發(fā)的查詢場(chǎng)景如果僅選擇一個(gè)或少數(shù)分桶列,則對(duì)應(yīng)的點(diǎn)查詢可以僅觸發(fā)一個(gè)分桶掃描(意味著可以做桶裁剪以減少數(shù)據(jù)查詢范圍)。此時(shí),當(dāng)多個(gè)點(diǎn)查詢并發(fā)時(shí),這些查詢有較大的概率分別觸發(fā)不同的分桶掃描,各個(gè)查詢之間的 IO 影響較小,尤其當(dāng)不同桶分布在不同磁盤上時(shí)),所以這種方式適合高并發(fā)的點(diǎn)查詢場(chǎng)景分桶的數(shù)量理論上沒有上限Join 方式
縱觀全局
作為一個(gè)分布式MPP數(shù)據(jù)庫,在加入的過程中需要對(duì)數(shù)據(jù)進(jìn)行混洗。需要對(duì)數(shù)據(jù)進(jìn)行分割和調(diào)度,以確保最終的連接結(jié)果是正確的。舉個(gè)簡單的例子,假設(shè)關(guān)系S和R是join,N代表join計(jì)算中涉及的節(jié)點(diǎn)數(shù);t代表關(guān)系的元組數(shù)。
目前多麗絲支持以上四種加入方式。這四種方法的靈活性和適用性由高到低,對(duì)數(shù)據(jù)分布的要求也越來越嚴(yán)格。但是通過減少網(wǎng)絡(luò)開銷,Join計(jì)算的性能越來越好。
連接方式的選擇是FE生成分布式計(jì)劃階段需要考慮的問題之一。FE做分布式計(jì)劃的時(shí)候,優(yōu)先級(jí)順序是(總是優(yōu)先選擇期望性能最好的):協(xié)同定位Join->:Bucket Shuffle Join->;廣播加入-& gt;隨機(jī)加入.
共存和桶混洗不能兼得。當(dāng)它們無法使用時(shí),多麗絲會(huì)自動(dòng)嘗試廣播加入,如果估計(jì)的小桌子太大,會(huì)自動(dòng)切換到洗牌加入。
但是,用戶可以通過顯式提示來強(qiáng)制所需的聯(lián)接類型,例如:
select * from test join [shuffle] baseall on test.k1 = baseall.k1;廣播/隨機(jī)加入
原理比較簡單,這里就不展開了。
桶洗牌加入
當(dāng)Join條件命中左表的數(shù)據(jù)分發(fā)列表時(shí),廣播和Shuffle Join會(huì)產(chǎn)生不必要的網(wǎng)絡(luò)傳輸開銷。Bucket Shuffle Join旨在解決這類問題。通過優(yōu)化左表的本地計(jì)算,可以減少左表數(shù)據(jù)在節(jié)點(diǎn)間的傳輸時(shí)間,從而加快查詢速度。
在上面的例子中,Join的等價(jià)表達(dá)式命中了表A(左邊的表)的數(shù)據(jù)分布列表。Bucket Shuffle Join會(huì)根據(jù)表A的數(shù)據(jù)分布信息將表B(右表)的數(shù)據(jù)發(fā)送到表A對(duì)應(yīng)的數(shù)據(jù)計(jì)算節(jié)點(diǎn)。
定性分析:
降低了網(wǎng)絡(luò)與內(nèi)存開銷(相比 Broadcast 以及 Shuffle Join 都不會(huì)更差),使一類 Join 查詢有更好的性能。尤其是當(dāng) FE 能夠執(zhí)行左表的分區(qū)裁剪與桶裁剪時(shí)與 Colocate Join 不同,它對(duì)于表的數(shù)據(jù)分布方式?jīng)]有侵入性,對(duì)于用戶來說是透明的。對(duì)于表的數(shù)據(jù)分布沒有強(qiáng)制性的要求(體現(xiàn)在建表語句中不需要顯式地設(shè)置 colocate_with 屬性),不容易導(dǎo)致數(shù)據(jù)傾斜的問題可以為 Join Reorder 提供更多可能的優(yōu)化空間計(jì)劃規(guī)則
Bucket Shuffle Join 只生效于 Join 條件為等值的場(chǎng)景,原因與 Colocate Join 類似,它們都依賴 Hash 來計(jì)算確定的數(shù)據(jù)分布在等值 Join 條件之中包含兩張表的分桶列,當(dāng)左表的分桶列為等值的 Join 條件時(shí),它有很大概率會(huì)被規(guī)劃為 Bucket Shuffle Join由于不同的數(shù)據(jù)類型的 Hash 值計(jì)算結(jié)果不同,所以 Bucket Shuffle Join 要求左表的分桶列的類型與右表等值 Join 列的類型需要保持一致,否則無法進(jìn)行對(duì)應(yīng)的規(guī)劃Bucket Shuffle Join 只作用于 Doris 原生的 OLAP 表,對(duì)于 ODBC,MySQL,ES 等外表,當(dāng)其作為左表時(shí)是無法規(guī)劃生效的對(duì)于分區(qū)表,由于每一個(gè)分區(qū)的數(shù)據(jù)分布規(guī)則可能不同,所以 Bucket Shuffle Join 只能保證左表為單分區(qū)時(shí)生效。所以在 SQL 執(zhí)行之中,需要盡量使用 where 條件使分區(qū)裁剪的策略能夠生效假如左表為 Colocate 的表,那么它每個(gè)分區(qū)的數(shù)據(jù)分布規(guī)則是確定的,Bucket Shuffle Join 能在Colocate 表上表現(xiàn)更好共址聯(lián)接
可以理解為在數(shù)據(jù)分布滿足一定條件的前提下,減少所有不必要的網(wǎng)絡(luò)傳輸開銷,實(shí)現(xiàn)完全計(jì)算本地化,加快查詢速度。同時(shí),由于沒有網(wǎng)絡(luò)傳輸開銷,be節(jié)點(diǎn)可以有更高的并發(fā)性,從而進(jìn)一步提高加入性能。
要理解這種算法,首先需要知道兩個(gè)術(shù)語:
Colocation Group(CG):一個(gè) CG 中會(huì)包含一張及以上的 Table。在同一個(gè) Group 內(nèi)的 Table 有著相同的 Colocation Group Schema,并且有著相同的數(shù)據(jù)分片分布Colocation Group Schema(CGS):用于描述一個(gè) CG 中的 Table,和 Colocation 相關(guān)的通用 Schema 信息。包括分桶列類型,分桶數(shù)以及副本數(shù)等桶序列的概念:
根據(jù)桶列值散列和桶的數(shù)量,一個(gè)表的數(shù)據(jù)最終將落入一個(gè)桶中。假設(shè)一個(gè)表的桶號(hào)是8,那么就有[0,1,2,3,4,5,6,7] 8個(gè)桶。我們稱這樣的序列為buckets序列。每個(gè)桶中會(huì)有一個(gè)或多個(gè)數(shù)據(jù)板。當(dāng)表是單個(gè)分區(qū)表時(shí),桶中只有一個(gè)Tablet。如果是多分區(qū)表,就會(huì)有多個(gè)(因?yàn)槎鄠€(gè)分區(qū)中的不同平板會(huì)被分到同一個(gè)桶中)。
Colorjoin功能是將一組具有相同CG的表格組合成一個(gè)CG。并且確保對(duì)應(yīng)于這些表的數(shù)據(jù)切片將落在相同的BE節(jié)點(diǎn)上。當(dāng)CG中的表以桶列連接時(shí),本地?cái)?shù)據(jù)可以直接連接,這樣可以減少節(jié)點(diǎn)間數(shù)據(jù)的傳輸時(shí)間。
[div][div]
因此,關(guān)鍵問題就變成了“如何保證這些表對(duì)應(yīng)的數(shù)據(jù)切片會(huì)落在同一個(gè)BE節(jié)點(diǎn)上?”?」
以下屬性必須在同一個(gè)CG through表中實(shí)現(xiàn):
分桶列和分桶數(shù)桶列,即DISTRIBUTED BY HASH(col1,col2,...)在建表的語句中。桶列決定了哪些列用于將表中的數(shù)據(jù)散列到不同的表中。同一個(gè)CG中的表必須保證桶列的類型和數(shù)量完全相同,桶號(hào)相同,這樣才能保證多個(gè)表的數(shù)據(jù)片能夠被一一分配和控制。
副本數(shù)同一CG中所有表的所有分區(qū)的副本數(shù)量必須相同。如果不一致,可能會(huì)出現(xiàn)某個(gè)Tablet的副本,而同一個(gè)BE上沒有其他table slices的副本。但是,對(duì)于同一CG中的表,分區(qū)的數(shù)量和范圍以及分區(qū)列的類型不需要一致。
[div][div]
在固定了bucket列和bucket號(hào)之后,同一CG中的表將具有相同的BucketsSequence。但是,副本的數(shù)量決定了每個(gè)桶中藥片的副本數(shù)量,以及它們存儲(chǔ)在哪個(gè)BEs上。假設(shè)BucketsSequence是[0,1,2,3,4,5,6,7]并且有[a,b,c,d]四個(gè)BE節(jié)點(diǎn)。那么可能的數(shù)據(jù)分布如下:
+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+| 0 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 |+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+| A | | B | | C | | D | | A | | B | | C | | D || | | | | | | | | | | | | | | || B | | C | | D | | A | | B | | C | | D | | A || | | | | | | | | | | | | | | || C | | D | | A | | B | | C | | D | | A | | B |+---+ +---+ +---+ +---+ +---+ +---+ +---+ +---+CG中所有表的數(shù)據(jù)都會(huì)按照上述規(guī)則均勻分布,從而保證所有桶和列值相同的數(shù)據(jù)都在同一個(gè)BE節(jié)點(diǎn)上,可以進(jìn)行本地?cái)?shù)據(jù)Join。其核心思想是“二次映射”,保證同一個(gè)分布式Key的數(shù)據(jù)會(huì)被映射到同一個(gè)桶序列,然后保證桶序列對(duì)應(yīng)的桶被映射到同一個(gè)BE節(jié)點(diǎn):
您可以通過查詢計(jì)劃檢查查詢是否使用了協(xié)同定位連接。同時(shí),計(jì)劃交換節(jié)點(diǎn)被刪除,ScanNode將被直接設(shè)置為Hash Join節(jié)點(diǎn)的子節(jié)點(diǎn)。
DESC SELECT * FROM tbl1 INNER JOIN tbl2 ON (tbl1.k2 = tbl2.k2);-- 在 Hash Join 節(jié)點(diǎn)會(huì)顯示:-- colocate: true/falseColocate Join非常適合將幾個(gè)表按照相同的字段劃分為桶,并按照固定的字段高頻連接的場(chǎng)景。這樣可以提前將數(shù)據(jù)存儲(chǔ)在同一個(gè)桶中,實(shí)現(xiàn)本地計(jì)算。
Runtime Filter 優(yōu)化
Doris在進(jìn)行哈希連接計(jì)算時(shí)會(huì)在右表中構(gòu)建一個(gè)哈希表,左表會(huì)流經(jīng)右表的哈希表得到連接結(jié)果。運(yùn)行時(shí)過濾器充分利用哈希表構(gòu)建階段對(duì)表做一些額外的事情。
在右表生成哈希表時(shí),還會(huì)生成一個(gè)基于哈希表數(shù)據(jù)的過濾條件,然后下推到左表的數(shù)據(jù)掃描節(jié)點(diǎn)。這樣,Doris可以在運(yùn)行時(shí)過濾數(shù)據(jù)。
如果左表是大表,右表是小表,那么下推到左表的過濾條件可以在讀取數(shù)據(jù)時(shí)提前過濾掉Join層的大部分待過濾數(shù)據(jù)(如果可以下推到引擎層,也可以使用Doris的鍵列過濾延遲物化),從而大大提高Join查詢的性能。
運(yùn)行時(shí)過濾器在查詢規(guī)劃期間生成,內(nèi)置于HashJoinNode中,并在ScanNode中應(yīng)用。比如T1(行數(shù)10w)和T2(行數(shù)2k)的Join運(yùn)算:
| > HashJoinNode <| | || | 100000 | 2000| | || OlapScanNode OlapScanNode| ^ ^ | | 100000 | 2000| T1 T2|顯然,掃描T2數(shù)據(jù)比T1快得多。如果我們?cè)趻呙鑄1之前主動(dòng)等待一段時(shí)間,在T2把掃描的數(shù)據(jù)記錄交給hashjonode之后,hashjonode根據(jù)T2數(shù)據(jù)計(jì)算一個(gè)過濾條件,比如T2數(shù)據(jù)的最大值和最小值,或者構(gòu)造一個(gè)Bloom Filter。然后把這個(gè)過濾條件發(fā)送給等待掃描T1的ScanNode,后者應(yīng)用這個(gè)過濾條件,把過濾后的數(shù)據(jù)交給HashJoinNode,這樣就減少了探針哈希表的次數(shù)和網(wǎng)絡(luò)開銷。該過濾條件為運(yùn)行時(shí)過濾,效果如下:
| > HashJoinNode <| | || | 6000 | 2000| | || OlapScanNode OlapScanNode| ^ ^ | | 100000 | 2000| T1 T2|如果可以將運(yùn)行時(shí)過濾器下推到存儲(chǔ)引擎,在某些情況下,可以使用索引(例如連接列是關(guān)鍵列,可以使用延遲物化能力)直接減少掃描數(shù)據(jù)量,從而大大減少掃描時(shí)間。效果如下:
| > HashJoinNode <| | || | 6000 | 2000| | || OlapScanNode OlapScanNode| ^ ^ | | 6000 | 2000| T1 T2|可以看出,與謂詞下推和分區(qū)裁剪不同,運(yùn)行時(shí)過濾是運(yùn)行時(shí)動(dòng)態(tài)生成的過濾條件,即在查詢運(yùn)行時(shí),解析連接條件確定過濾表達(dá)式,并將表達(dá)式下推至讀取左表的ScanNode,從而減少掃描數(shù)據(jù)量,進(jìn)一步減少探針哈希表數(shù)量,避免不必要的IO和網(wǎng)絡(luò)傳輸。由于其運(yùn)行時(shí)有效的特性,它被正式視為自適應(yīng)查詢執(zhí)行的應(yīng)用程序。
根據(jù)上面的例子可以推斷,當(dāng)場(chǎng)景滿足以下條件時(shí),使用運(yùn)行時(shí)濾鏡的效果會(huì)更好:
左表大右表小(當(dāng)右表上還有額外的過濾條件會(huì)更理想),因?yàn)闃?gòu)建 Runtime Filter 是需要承擔(dān)計(jì)算成本的,包括一些內(nèi)存的開銷,而開銷直接取決于右表的實(shí)際數(shù)據(jù)量左右表 Join 出來的結(jié)果很少,說明通過 Runtime Filter 可以過濾掉左表的絕大部分?jǐn)?shù)據(jù)Doris支持三種運(yùn)行時(shí)過濾器:
一種是 IN,很好理解,將一個(gè) hashset 下推到數(shù)據(jù)掃描節(jié)點(diǎn)。第二種就是 BloomFilter,就是利用哈希表的數(shù)據(jù)構(gòu)造一個(gè) BloomFilter,然后把這個(gè) BloomFilter 下推到查詢數(shù)據(jù)的掃描節(jié)點(diǎn)。最后一種就是 MinMax,就是個(gè) Range 范圍,通過右表數(shù)據(jù)確定 Range 范圍之后,下推給數(shù)據(jù)掃描節(jié)點(diǎn)。工作原理和優(yōu)缺點(diǎn)總結(jié)如下:
Runtime Filter 類型工作原理適用場(chǎng)景優(yōu)點(diǎn)缺點(diǎn)IN子查詢的方式,實(shí)現(xiàn)上是將一個(gè) Hashset 下推到 Scan 節(jié)點(diǎn)Broadcast Join開銷小,過濾效果明顯且快速右表超過一定數(shù)據(jù)量時(shí)會(huì)失效,目前 Doris 配置的閾值是 1024Min/Max通過右表構(gòu)建一個(gè) Range 范圍,然后將它下推到 Scan 節(jié)點(diǎn)通用開銷小僅對(duì)數(shù)值類型有效果;對(duì)數(shù)值以外類型無法使用BloomFilter通過右表構(gòu)建一個(gè) BloomFilter,然后將它下推到 Scan 節(jié)點(diǎn)通用通用性較好,適用于各種類型、效果也較好配置比較復(fù)雜且計(jì)算成本較高;當(dāng)過濾率較低或者左表數(shù)據(jù)較少時(shí),可能導(dǎo)致性能降低一些使用注意事項(xiàng)(比較細(xì)節(jié),考慮后面結(jié)合代碼進(jìn)一步理解):
打開運(yùn)行時(shí)過濾器后,左表中的ScanNode在掃描數(shù)據(jù)前,會(huì)為分配給自己的每個(gè)運(yùn)行時(shí)過濾器等待一段時(shí)間,也就是說,如果ScanNode被分配了三個(gè)運(yùn)行時(shí)過濾器,最多等待3000ms。
因?yàn)闃?gòu)建和合并Runtimefilters需要時(shí)間,所以ScanNode會(huì)嘗試將在等待時(shí)間內(nèi)到達(dá)的Runtimefilters推送到存儲(chǔ)引擎。如果超過等待時(shí)間,ScanNode將使用已經(jīng)到達(dá)的Runtimefilters直接開始掃描數(shù)據(jù)。
如果運(yùn)行時(shí)過濾器在ScanNode開始掃描之后到達(dá),則ScanNode不會(huì)將運(yùn)行時(shí)過濾器下推到存儲(chǔ)引擎,而是基于ScanNode上的運(yùn)行時(shí)過濾器過濾從存儲(chǔ)引擎掃描的數(shù)據(jù),并且不會(huì)將運(yùn)行時(shí)過濾器應(yīng)用于先前掃描的數(shù)據(jù),這樣獲得的中間數(shù)據(jù)的大小將大于最優(yōu)解,但可以避免嚴(yán)重惡化。
如果集群很忙,并且集群上有許多資源密集型或耗時(shí)的查詢,您可以考慮增加等待時(shí)間,以避免復(fù)雜查詢錯(cuò)過優(yōu)化機(jī)會(huì)。如果集群負(fù)載較輕,并且集群上有許多只需要幾秒鐘的小查詢,那么可以考慮減少等待時(shí)間,以避免每個(gè)查詢?cè)黾?s的延遲。
Join Reorder 優(yōu)化
有了前面兩個(gè)表連接的運(yùn)行時(shí)過濾器鋪墊,再加上連接重新排序的優(yōu)化,邏輯關(guān)系就可以理順了。
Doris目前的Join Reorder算法是基于RBO的,其邏輯描述如下:
盡量讓大表跟小表做 Join,它生成的中間結(jié)果是盡可能小的把有條件的 Join 表往前放,也就是說盡量讓有條件的 Join 表進(jìn)行過濾Hash Join 的優(yōu)先級(jí)高于 Nest Loop Join,因?yàn)?Hash join 本身是比 Nest Loop Join 快很多的可以發(fā)現(xiàn),前兩個(gè)是朝著讓“右表”更小的方向優(yōu)化的,而最后一個(gè)是從算法的性能上考慮的。
Join 調(diào)優(yōu)建議
Join 列最好是相同的簡單類型;同類型避免 Cast 操作,簡單類型則有不錯(cuò)的 Join 計(jì)算性能Join 列最好是 Key 列,原因是 Key 列能夠充分利用 Doris 延遲物化的特性,減少 IO 提升性能大表之間的 Join 最好能夠利用上 Colocate,相當(dāng)于已經(jīng)做好了預(yù) Shuffle,實(shí)際查詢的時(shí)候可以直接 Join 計(jì)算不再有 Shuffle 操作,徹底避免了大表的 Shuffle 網(wǎng)絡(luò)開銷利用 Runtime Filter,Join 過濾性高時(shí)效果顯著。根據(jù) 3 種 Runtime Filter 特點(diǎn)選擇最適合的涉及多表 Join,需要判斷 Join 的合理性。盡量保證“左大右小”的原則,HashJoin 優(yōu)于 NLJ。必要時(shí)可以通過 SQL Rewrite,通過 Hint 來調(diào)整 Join 順序裁判員
https://www.jb51.net/article/266004.htm
https://www.jb51.net/article/266000.htm
以上是Apache Doris加入優(yōu)化原理的詳細(xì)內(nèi)容。更多關(guān)于Apache Doris Join優(yōu)化的信息,請(qǐng)關(guān)注腳本之家的其他相關(guān)文章!
如果您的問題還未解決可以聯(lián)系站長付費(fèi)協(xié)助。

有問題可以加入技術(shù)QQ群一起交流學(xué)習(xí)
本站vip會(huì)員 請(qǐng)加入無憂模板網(wǎng) VIP群(50604020) PS:加入時(shí)備注用戶名或昵稱
普通注冊(cè)會(huì)員或訪客 請(qǐng)加入無憂模板網(wǎng) 技術(shù)交流群(50604130)
客服微信號(hào):15898888535
聲明:本站所有文章資源內(nèi)容,如無特殊說明或標(biāo)注,均為采集網(wǎng)絡(luò)資源。如若內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系站長刪除。