<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ClickHouse要了解的騷氣join操作

          共 3910字,需瀏覽 8分鐘

           ·

          2021-07-12 18:04

          原文鏈接:https://zhuanlan.zhihu.com/p/377506070
          JOIN操作是OLAP場景無法繞開的,且使用廣泛的操作。對ClickHouse而言,非常有必要對分布式JOIN實現(xiàn)作深入研究。
          在介紹分布式JOIN之前,我們看看ClickHouse 單機JOIN是如何實現(xiàn)的。

          1. ClickHouse單機JOIN實現(xiàn)

          ClickHouse 單機JOIN操作默認采用HASH JOIN算法,可選MERGE JOIN算法。其中,MERGE JOIN算法數(shù)據(jù)會溢出到磁盤,性能相比前者較差。本文重點介紹基于HASH JOIN算法的實現(xiàn)JOIN操作。
          ClickHouse JOIN查詢語法如下:
          SELECT <expr_list>FROM <left_table>[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN <right_table>(ON <expr_list>)|(USING <column_list>) ...
          ClickHouse 的 HASH JOIN算法實現(xiàn)比較簡單:
          • 從right_table 讀取該表全量數(shù)據(jù),在內(nèi)存中構建HASH MAP;
          • 從left_table 分批讀取數(shù)據(jù),根據(jù)JOIN KEY到HASH MAP中進行查找,如果命中,則該數(shù)據(jù)作為JOIN的輸出;
          從這個實現(xiàn)中可以看出,如果right_table的數(shù)據(jù)量超過單機可用內(nèi)存空間的限制,則JOIN操作無法完成。通常,兩表JOIN時,將較小表作為right_table.

          2. ClickHouse分布式JOIN實現(xiàn)

          ClickHouse 是去中心化架構,非常容易水平擴展集群。當以集群模式提供服務時候,分布式JOIN查詢就無法避免。這里的分布式JOIN通常指,JOIN查詢中涉及到的left_table 與 right_table 是分布式表。
          通常,分布式JOIN實現(xiàn)機制無非如下幾種:
          • Broadcast JOIN
          • Shuffle Join
          • Colocate JOIN
          ClickHouse集群并未實現(xiàn)完整意義上的Shuffle JOIN,實現(xiàn)了類Broadcast JOIN,通過事先完成數(shù)據(jù)重分布,能夠?qū)崿F(xiàn)Colocate JOIN。
          ClickHouse 的分布式JOIN查詢可以分為兩類,帶GLOBAL關鍵字的,和不帶GLOBAL關鍵字的情況。

          2.1 普通JOIN實現(xiàn)

          2.1 中描述了GLOBAL JOIN的實現(xiàn)。接下來看看無GLOBAL關鍵字的JOIN如何實現(xiàn)的:
          • a. initiator 將SQL S中左表分布式表替換為對應的本地表,形成S'
          • b. initiator 將a.中的S'分發(fā)到集群每個節(jié)點
          • c. 集群節(jié)點執(zhí)行S',并將結果匯總到initiator 節(jié)點
          • d. initiator 節(jié)點將結果返回給客戶端
          如果右表為分布式表,則集群中每個節(jié)點會去執(zhí)行分布式查詢。這里就會存在一個非常嚴重的讀放大現(xiàn)象。假設集群有N個節(jié)點,右表查詢會在集群中執(zhí)行N*N次。

          如圖所示,假設執(zhí)行的SQL為:

          SELECT a_.i, a_.s, b_.t FROM a_all as a_ JOIN b_all AS b_ ON a_.i = b_.i
          其中,a_all, b_all為分布式表,對應的本地表名為a_local, b_local。則改SQL在分布式執(zhí)行的時序為:
          • 1)initiator 收到查詢請求
          • 2) initiator 執(zhí)行分布式查詢,本節(jié)點和其他節(jié)點執(zhí)行SELECT a_.i, a_.s, b_.t FROM a_local AS a_ JOIN b_all as b_ ON a_.i = b_.i即左表分布式表更改為本地表名。
            該SQL在集群范圍內(nèi)并行執(zhí)行。
          • 3)集群節(jié)點收到2)中SQL后,分析出右表時分布式表,則觸發(fā)一次分布式查詢:
            SELECT b_.i, b_.t FROM b_local AS b_ 集群各節(jié)點并發(fā)執(zhí)行,并合并結果,記為subquery.
          • 4)集群節(jié)點完成3)中SQL執(zhí)行后,執(zhí)行 SELECT a_.i, a_.s, b_.t FROM a_local AS a_ JOIN subquery as b_ ON a_.i = b_.i其中subquery表示2中執(zhí)行的結果
          • 5) 各節(jié)點執(zhí)行完成JOIN計算后,向initiator節(jié)點發(fā)送數(shù)據(jù)
          可以看出,ClickHouse 普通分布式JOIN查詢是一個簡單版的Shuffle JOIN的實現(xiàn),或者說是一個不完整的實現(xiàn)。不完整的地方在于,并未按JOIN KEY去Shuffle數(shù)據(jù),而是每個節(jié)點全量拉去右表數(shù)據(jù)。這里實際上是存在著優(yōu)化空間的。
          在生產(chǎn)環(huán)境中,查詢放大對查詢性能的影響是不可忽略的。

          2.2 GLOBAL JOIN 實現(xiàn)

          GLOBAL JOIN 計算過程如下:
          • a. 若右表為子查詢,則initiator完成子查詢計算;
          • b. initiator 將右表數(shù)據(jù)發(fā)送給集群其他節(jié)點;
          • c. 集群節(jié)點將左表本地表與右表數(shù)據(jù)進行JOIN計算;
          • d. 集群其他節(jié)點將結果發(fā)回給initiator節(jié)點;
          • e. initiator 將結果匯總,發(fā)給客戶端;
          GLOBAL JOIN 可以看做一個不完整的Broadcast JOIN實現(xiàn)。如果JOIN的右表數(shù)據(jù)量較大,就會占用大量網(wǎng)絡帶寬,導致查詢性能降低。

          如圖所示,假設執(zhí)行的SQL為:

          SELECT a_.i, a_.s, b_.t FROM a_all as a_ GLOBAL JOIN b_all AS b_ ON a_.i = b_.i
          其中,a_all, b_all為分布式表,對應的本地表名為a_local, b_local。則改SQL在分布式執(zhí)行的時序為:
          • 1)initiator 收到查詢請求
          • 2) initiator 和集群其他節(jié)點均執(zhí)行SELECT b_.i, b_.t FROM b_local AS b_ 即左表分布式表更改為本地表名。
            該SQL在集群范圍內(nèi)并行執(zhí)行。
            匯總結果,記錄為subquery。
          • 3)initiator 將2)中subquery發(fā)送到集群中其他節(jié)點,并觸發(fā)分布式查詢:
            SELECT a_.i, a_.s, b_.t FROM a_local AS a_ JOIN subquery as b_ ON a_.i = b_.i其中subquery表示2)中執(zhí)行的結果
          • 4) 各節(jié)點執(zhí)行完成JOIN計算后,向initiator節(jié)點發(fā)送數(shù)據(jù)
          可以看出,GLOBAL JOIN 將右表的查詢在initiator節(jié)點上完成后,通過網(wǎng)絡發(fā)送到其他節(jié)點,避免其他節(jié)點重復計算,從而避免查詢放大。

          3. 分布式JOIN最佳實踐

          在清楚了ClickHouse 分布式JOIN查詢實現(xiàn)后,我們總結一些實際經(jīng)驗。
          • 一、盡量減少JOIN右表數(shù)據(jù)量
          ClickHouse根據(jù)JOIN的右表數(shù)據(jù),構建HASH MAP,并將SQL中所需的列全部讀入內(nèi)存中。如果右表數(shù)據(jù)量過大,節(jié)點內(nèi)存無法容納后,無法完成計算。
          在實際中,我們通常將較小的表作為右表,并盡可能增加過濾條件,降低進入JOIN計算的數(shù)據(jù)量。
          • 二、利用GLOBAL JOIN 避免查詢放大帶來性能損失
          如果右表或者子查詢的數(shù)據(jù)量可控,可以使用GLOBAL JOIN來避免讀放大。需要注意的是,GLOBAL JOIN 會觸發(fā)數(shù)據(jù)在節(jié)點之間傳播,占用部分網(wǎng)絡流量。如果數(shù)據(jù)量較大,同樣會帶來性能損失。
          • 三、數(shù)據(jù)預分布實現(xiàn)Colocate JOIN
          當JOIN涉及的表數(shù)據(jù)量都非常大時,讀放大,或網(wǎng)絡廣播都帶來巨大性能損失時,我們就需要采取另外一種方式來完成JOIN計算了。
          根據(jù)“相同JOIN KEY必定相同分片”原理,我們將涉及JOIN計算的表,按JOIN KEY在集群維度作分片。將分布式JOIN轉(zhuǎn)為為節(jié)點的本地JOIN,極大減少了查詢放大問題。
          如果如下操作:
          • 將涉及JOIN的表按JOIN KEY分片
          • 根據(jù)2.2節(jié)描述,將JOIN預計中右表換成相應的本地表

          如圖所示,執(zhí)行的SQL為:

          SELECT a_.i, a_.s, b_.t FROM a_all as a_ JOIN b_local AS b_ ON a_.i = b_.i
          其中,a_all, b_all為分布式表,對應的本地表名為a_local, b_local。則改SQL在分布式執(zhí)行的時序為:
          • 1)initiator 收到查詢請求
          • 2)initiator 發(fā)起一次分布式查詢,本機以及其他節(jié)點執(zhí)行:
            SELECT a_.i, a_.s, b_.t FROM a_local AS a_ JOIN b_local as b_ ON a_.i = b_.i
          • 3) 各節(jié)點執(zhí)行完成JOIN計算后,向initiator節(jié)點發(fā)送數(shù)據(jù)
          由于數(shù)據(jù)以及預分區(qū)了,相同的JOIN KEY對應的數(shù)據(jù)一定在一起,不會跨節(jié)點存在,所以無需對右表做分布式查詢,也能獲得正確結果。

          4. 總結

          本文介紹了ClickHouse JOIN實現(xiàn)原理,并根據(jù)原理介紹了相關的最佳實踐:
          • 減少JOIN右表數(shù)據(jù)量
          • 避免查詢放大帶來性能損失
          • 數(shù)據(jù)預分布實現(xiàn)Colocate JOIN;
          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天色官网| 黄色免费国产视频 | 豆花av在线观看 豆花AV在线入口 豆花精品在线视频 | 国内精品在线看 | 毛片小电影 |