ClickHouse原理 | ClickHouse特性及底層儲存原理
ClickHouse的特性
ClickHouse 是一款 MPP 架構的列式儲存資料庫,但 MPP 和列式儲存並不是什麼 " 稀罕 " 的設計。擁有類似架構的其他資料庫產品也有很多,但是為什麼偏偏只有 ClickHouse 的效能如此出眾呢? ClickHouse 發展至今的演進過程一共經歷了四個階段,每一次階段演進,相比之前都進一步取其精華去其糟粕。可以說 ClickHouse 汲取了各家技術的精髓,將每一個細節都做到了極致。接下來將介紹 ClickHouse 的一些核心特性,正是這些特性形成的合力使得 ClickHouse 如此優秀。
01 完備的DBMS功能
ClickHouse 擁有完備的管理功能,所以它稱得上是一個 DBMS ( Database Management System ,資料庫管理系統 ) ,而不僅是一個數據庫。作為一個 DBMS ,它具備了一些基本功能,如下所示。
•DDL ( 資料定義語言 ) :可以動態地建立、修改或刪除資料庫、表和檢視,而無須重啟服務。
•DML ( 資料操作語言 ) :可以動態查詢、插入、修改或刪除資料。
•許可權控制:可以按照使用者粒度設定資料庫或者表的操作許可權,保障資料的安全性。
•資料備份與恢復:提供了資料備份匯出與匯入恢復機制,滿足生產環境的要求。
•分散式管理:提供叢集模式,能夠自動管理多個數據庫節點。
這裡只列舉了一些最具代表性的功能,但已然足以表明為什麼 Click House 稱得上是 DBMS 了。
02 列式儲存與資料壓縮
列式儲存和資料壓縮,對於一款高效能資料庫來說是必不可少的特性。一個非常流行的觀點認為,如果你想讓查詢變得更快,最簡單且有效的方法是減少資料掃描範圍和資料傳輸時的大小,而列式儲存和資料壓縮就可以幫助我們實現上述兩點。列式儲存和資料壓縮通常是伴生的,因為一般來說列式儲存是資料壓縮的前提。
按列儲存與按行儲存相比,前者可以有效減少查詢時所需掃描的資料量,這一點可以用一個示例簡單說明。假設一張資料表 A 擁有 50 個欄位 A1 ~ A50 ,以及 100 行資料。
按列儲存相比按行儲存的另一個優勢是對資料壓縮的友好性。同樣可以用一個示例簡單說明壓縮的本質是什麼。假設有兩個字串 abcdefghi 和 bcdefghi ,現在對它們進行壓縮,如下所示:
壓縮前: abcdefghi_bcdefghi
壓縮後: abcdefghi_(9,8)
可以看到,壓縮的本質是按照一定步長對資料進行匹配掃描,當發現重複部分的時候就進行編碼轉換。例如上述示例中的 (9 , 8) ,表示如果從下劃線開始向前移動 9 個位元組,會匹配到 8 個位元組長度的重複項,即這裡的 bcdefghi 。
真實的壓縮演算法自然比這個示例更為複雜,但壓縮的實質就是如此。資料中的重複項越多,則壓縮率越高;壓縮率越高,則資料體量越小;而資料體量越小,則資料在網路中的傳輸越快,對網路頻寬和磁碟 IO 的壓力也就越小。既然如此,那怎樣的資料最可能具備重複的特性呢?答案是屬於同一個列欄位的資料,因為它們擁有相同的資料型別和現實語義,重複項的可能性自然就更高。
ClickHouse 就是一款使用列式儲存的資料庫,資料按列進行組織,屬於同一列的資料會被儲存在一起,列與列之間也會由不同的檔案分別儲存 ( 這裡主要指 MergeTree 表引擎 ) 。資料預設使用 LZ4 演算法壓縮,在 Yandex.Metrica 的生產環境中,資料總體的壓縮比可以達到 8:1 ( 未壓縮前 17PB ,壓縮後 2PB ) 。列式儲存除了降低 IO 和儲存的壓力之外,還為向量化執行做好了鋪墊。
03 向量化執行引擎
坊間有句玩笑,即 " 能用錢解決的問題,千萬別花時間 " 。而業界也有種調侃如出一轍,即 " 能升級硬體解決的問題,千萬別優化程式 " 。有時候,你千辛萬苦優化程式邏輯帶來的效能提升,還不如直接升級硬體來得簡單直接。這雖然只是一句玩笑不能當真,但硬體層面的優化確實是最直接、最高效的提升途徑之一。向量化執行就是這種方式的典型代表,這項暫存器硬體層面的特性,為上層應用程式的效能帶來了指數級的提升。
向量化執行,可以簡單地看作一項消除程式中迴圈的優化。這裡用一個形象的例子比喻。小胡經營了一家果汁店,雖然店裡的鮮榨蘋果汁深受大家喜愛,但客戶總是抱怨製作果汁的速度太慢。小胡的店裡只有一臺榨汁機,每次他都會從籃子裡拿出一個蘋果,放到榨汁機內等待出汁。如果有 8 個客戶,每個客戶都點了一杯蘋果汁,那麼小胡需要重複迴圈 8 次上述的榨汁流程,才能榨出 8 杯蘋果汁。如果製作一杯果汁需要 5 分鐘,那麼全部製作完畢則需要 40 分鐘。為了提升果汁的製作速度,小胡想出了一個辦法。他將榨汁機的數量從 1 臺增加到了 8 臺,這麼一來,他就可以從籃子裡一次性拿出 8 個蘋果,分別放入 8 臺榨汁機同時榨汁。此時,小胡只需要 5 分鐘就能夠製作出 8 杯蘋果汁。為了製作 n 杯果汁,非向量化執行的方式是用 1 臺榨汁機重複迴圈制作 n 次,而向量化執行的方式是用 n 臺榨汁機只執行 1 次。
為了實現向量化執行,需要利用 CPU 的 SIMD 指令。 SIMD 的全稱是 Single Instruction Multiple Data ,即用單條指令操作多條資料。現代計算機系統概念中,它是通過資料並行以提高效能的一種實現方式 ( 其他的還有指令級並行和執行緒級並行 ) ,它的原理是在 CPU 暫存器層面實現資料的並行操作。
在計算機系統的體系結構中,儲存系統是一種層次結構。典型伺服器計算機的儲存層次結構如圖 1 所示。一個實用的經驗告訴我們,儲存媒介距離 CPU 越近,則訪問資料的速度越快。
從上圖中可以看到,從左向右,距離 CPU 越遠,則資料的訪問速度越慢。從暫存器中訪問資料的速度,是從記憶體訪問資料速度的 300 倍,是從磁碟中訪問資料速度的 3000 萬倍。所以利用 CPU 向量化執行的特性,對於程式的效能提升意義非凡。
ClickHouse 目前利用 SSE4.2 指令集實現向量化執行。
04 關係模型與SQL查詢
相比 HBase 和 Redis 這類 NoSQL 資料庫, ClickHouse 使用關係模型描述資料並提供了傳統資料庫的概念 ( 資料庫、表、檢視和函式等 ) 。與此同時, ClickHouse 完全使用 SQL 作為查詢語言 ( 支援 GROUP BY 、 ORDER BY 、 JOIN 、 IN 等大部分標準 SQL ) ,這使得它平易近人,容易理解和學習。因為關係型資料庫和 SQL 語言,可以說是軟體領域發展至今應用最為廣泛的技術之一,擁有極高的 " 群眾基礎 " 。也正因為 ClickHouse 提供了標準協議的 SQL 查詢介面,使得現有的第三方分析視覺化系統可以輕鬆與它整合對接。在 SQL 解析方面, ClickHouse 是大小寫敏感的,這意味著 SELECT a 和 SELECT A 所代表的語義是不同的。
關係模型相比文件和鍵值對等其他模型,擁有更好的描述能力,也能夠更加清晰地表述實體間的關係。更重要的是,在 OLAP 領域,已有的大量資料建模工作都是基於關係模型展開的 ( 星型模型、雪花模型乃至寬表模型 ) 。 ClickHouse 使用了關係模型,所以將構建在傳統關係型資料庫或資料倉庫之上的系統遷移到 ClickHouse 的成本會變得更低,可以直接沿用之前的經驗成果。
05 多樣化的表引擎
也許因為 Yandex.Metrica 的最初架構是基於 MySQL 實現的,所以在 ClickHouse 的設計中,能夠察覺到一些 MySQL 的影子,表引擎的設計就是其中之一。與 MySQL 類似, ClickHouse 也將儲存部分進行了抽象,把儲存引擎作為一層獨立的介面。截至本書完稿時, ClickHouse 共擁有合併樹、記憶體、檔案、介面和其他 6 大類 20 多種表引擎。其中每一種表引擎都有著各自的特點,使用者可以根據實際業務場景的要求,選擇合適的表引擎使用。
通常而言,一個通用系統意味著更廣泛的適用性,能夠適應更多的場景。但通用的另一種解釋是平庸,因為它無法在所有場景內都做到極致。
在軟體的世界中,並不會存在一個能夠適用任何場景的通用系統,為了突出某項特性,勢必會在別處有所取捨。其實世間萬物都遵循著這樣的道理,就像信天翁和蜂鳥,雖然都屬於鳥類,但它們各自的特點卻鑄就了完全不同的體貌特徵。信天翁擅長遠距離飛行,環繞地球一週只需要 1 至 2 個月的時間。因為它能夠長時間處於滑行狀態, 5 天才需要扇動一次翅膀,心率能夠保持在每分鐘 100 至 200 次之間。而蜂鳥能夠垂直懸停飛行,每秒可以揮動翅膀 70 ~ 100 次,飛行時的心率能夠達到每分鐘 1000 次。如果用資料庫的場景類比信天翁和蜂鳥的特點,那麼信天翁代表的可能是使用普通硬體就能實現高效能的設計思路,資料按粗粒度處理,通過批處理的方式執行;而蜂鳥代表的可能是按細粒度處理資料的設計思路,需要高效能硬體的支援。
將表引擎獨立設計的好處是顯而易見的,通過特定的表引擎支撐特定的場景,十分靈活。對於簡單的場景,可直接使用簡單的引擎降低成本,而複雜的場景也有合適的選擇。
06 多執行緒與分散式
ClickHouse 幾乎具備現代化高效能資料庫的所有典型特徵,對於可以提升效能的手段可謂是一一用盡,對於多執行緒和分散式這類被廣泛使用的技術,自然更是不在話下。
如果說向量化執行是通過資料級並行的方式提升了效能,那麼多執行緒處理就是通過執行緒級並行的方式實現了效能的提升。相比基於底層硬體實現的向量化執行 SIMD ,執行緒級並行通常由更高層次的軟體層面控制。現代計算機系統早已普及了多處理器架構,所以現今市面上的伺服器都具備良好的多核心多執行緒處理能力。由於 SIMD 不適合用於帶有較多分支判斷的場景, ClickHouse 也大量使用了多執行緒技術以實現提速,以此和向量化執行形成互補。
如果一個籃子裝不下所有的雞蛋,那麼就多用幾個籃子來裝,這就是分散式設計中分而治之的基本思想。同理,如果一臺伺服器效能吃緊,那麼就利用多臺服務的資源協同處理。為了實現這一目標,首先需要在資料層面實現資料的分散式。因為在分散式領域,存在一條金科玉律—計算移動比資料移動更加划算。在各伺服器之間,通過網路傳輸資料的成本是高昂的,所以相比移動資料,更為聰明的做法是預先將資料分佈到各臺伺服器,將資料的計算查詢直接下推到資料所在的伺服器。 ClickHouse 在資料存取方面,既支援分割槽 ( 縱向擴充套件,利用多執行緒原理 ) ,也支援分片 ( 橫向擴充套件,利用分散式原理 ) ,可以說是將多執行緒和分散式的技術應用到了極致。
07 多主架構
HDFS 、 Spark 、 HBase 和 Elasticsearch 這類分散式系統,都採用了 Master-Slave 主從架構,由一個管控節點作為 Leader 統籌全域性。而 ClickHouse 則採用 Multi-Master 多主架構,叢集中的每個節點角色對等,客戶端訪問任意一個節點都能得到相同的效果。這種多主的架構有許多優勢,例如對等的角色使系統架構變得更加簡單,不用再區分主控節點、資料節點和計算節點,叢集中的所有節點功能相同。所以它天然規避了單點故障的問題,非常適合用於多資料中心、異地多活的場景。
08 線上查詢
ClickHouse 經常會被拿來與其他的分析型資料庫作對比,比如 Vertica 、 SparkSQL 、 Hive 和 Elasticsearch 等,它與這些資料庫確實存在許多相似之處。例如,它們都可以支撐海量資料的查詢場景,都擁有分散式架構,都支援列存、資料分片、計算下推等特性。這其實也側面說明了 ClickHouse 在設計上確實吸取了各路奇技淫巧。與其他資料庫相比, ClickHouse 也擁有明顯的優勢。例如, Vertica 這類商用軟體價格高昂; SparkSQL 與 Hive 這類系統無法保障 90% 的查詢在 1 秒內返回,在大資料量下的複雜查詢可能會需要分鐘級的響應時間;而 Elasticsearch 這類搜尋引擎在處理億級資料聚合查詢時則顯得捉襟見肘。
正如 ClickHouse 的 " 廣告詞 " 所言,其他的開源系統太慢,商用的系統太貴,只有 Clickouse 在成本與效能之間做到了良好平衡,即又快又開源。 ClickHouse 當之無愧地闡釋了 " 線上 " 二字的含義,即便是在複雜查詢的場景下,它也能夠做到極快響應,且無須對資料進行任何預處理加工。
09 Leetcode超級會員資料分片與分散式查詢
資料分片是將資料進行橫向切分,這是一種在面對海量資料的場景下,解決儲存和查詢瓶頸的有效手段,是一種分治思想的體現。 ClickHouse 支援分片,而分片則依賴叢集。每個叢集由 1 到多個分片組成,而每個分片則對應了 ClickHouse 的 1 個服務節點。分片的數量上限取決於節點數量 ( 1 個分片只能對應 1 個服務節點 ) 。
ClickHouse 並不像其他分散式系統那樣,擁有高度自動化的分片功能。 ClickHouse 提供了本地表 ( Local Table ) 與分散式表 ( Distributed Table ) 的概念。一張本地表等同於一份資料的分片。而分散式表本身不儲存任何資料,它是本地表的訪問代理,其作用類似分庫中介軟體。藉助分散式表,能夠代理訪問多個數據分片,從而實現分散式查詢。
這種設計類似資料庫的分庫和分表,十分靈活。例如在業務系統上線的初期,資料體量並不高,此時資料表並不需要多個分片。所以使用單個節點的本地表 ( 單個數據分片 ) 即可滿足業務需求,待到業務增長、資料量增大的時候,再通過新增資料分片的方式分流資料,並通過分散式表實現分散式查詢。這就好比一輛手動擋賽車,它將所有的選擇權都交到了使用者的手中。
雲原生概念的誕生ClickHouse儲存層
ClickHouse 從 OLAP 場景需求出發,定製開發了一套全新的高效列式儲存引擎,並且實現了資料有序儲存、主鍵索引、稀疏索引、資料 Sharding 、資料 Partitioning 、 TTL 、主備複製等豐富功能。以上功能共同為 ClickHouse 極速的分析效能奠定了基礎。
列式儲存
與行存將每一行的資料連續儲存不同,列存將每一列的資料連續儲存。示例圖如下:
相比於行式儲存,列式儲存在分析場景下有著許多優良的特性。
1 )如前所述,分析場景中往往需要讀大量行但是少數幾個列。在行存模式下,資料按行連續儲存,所有列的資料都儲存在一個 block 中,不參與計算的列在 IO 時也要全部讀出,讀取操作被嚴重放大。而列存模式下,只需要讀取參與計算的列即可,極大的減低了 IO cost ,加速了查詢。
2 )同一列中的資料屬於同一型別,壓縮效果顯著。列存往往有著高達十倍甚至更高的壓縮比,節省了大量的儲存空間,降低了儲存成本。
3 )更高的壓縮比意味著更小的 data size ,從磁碟中讀取相應資料耗時更短。
4 )自由的壓縮演算法選擇。不同列的資料具有不同的資料型別,適用的壓縮演算法也就不盡相同。可以針對不同列型別,選擇最合適的壓縮演算法。
5 )高壓縮比,意味著同等大小的記憶體能夠存放更多資料,系統 cache 效果更好。
資料有序儲存
ClickHouse 支援在建表時,指定將資料按照某些列進行 sort by 。
排序後,保證了相同 sort key 的資料在磁碟上連續儲存,且有序擺放。在進行等值、範圍查詢時, where 條件命中的資料都緊密儲存在一個或若干個連續的 Block 中,而不是分散的儲存在任意多個 Block , 大幅減少需要 IO 的 block 數量。另外,連續 IO 也能夠充分利用作業系統 page cache 的預取能力,減少 page fault 。
主鍵索引
ClickHouse 支援主鍵索引,它將每列資料按照 index granularity (預設 8192 行)進行劃分,每個 index granularity 的開頭第一行被稱為一個 mark 行。主鍵索引儲存該 mark 行對應的 primary key 的值。
對於 where 條件中含有 primary key 的查詢,通過對主鍵索引進行二分查詢,能夠直接定位到對應的 index granularity ,避免了全表掃描從而加速查詢。
但是值得注意的是: ClickHouse 的主鍵索引與 MySQL 等資料庫不同,它並不用於去重,即便 primary key 相同的行,也可以同時存在於資料庫中。要想實現去重效果,需要結合具體的表引擎 ReplacingMergeTree 、 CollapsingMergeTree 、 VersionedCollapsingMergeTree 實現,我們會在未來的文章系列中再進行詳細解讀。
資料插入、更新、刪除
Clickhouse 是個分析型資料庫。這種場景下,資料一般是不變的,因此 Clickhouse 對 update 、 delete 的支援是比較弱的,實際上並不支援標準的 update 、 delete 操作。
Clickhouse 通過 alter 方式實現更新、刪除,它把 update 、 delete 操作叫做 mutation( 突變 ) 。
標準 SQL 的更新、刪除操作是同步的,即客戶端要等服務端反回執行結果(通常是 int 值);而 Clickhouse 的 update 、 delete 是通過非同步方式實現的,當執行 update 語句時,服務端立即反回,但是實際上此時資料還沒變,而是排隊等著。
Mutation 具體過程
首先,使用 where 條件找到需要修改的分割槽;然後,重建每個分割槽,用新的分割槽替換舊的,分割槽一旦被替換,就不可回退;對於每個分割槽,可以認為是原子性的;但對於整個 mutation ,如果涉及多個分割槽,則不是原子性的。
• 更新功能不支援更新有關主鍵或分割槽鍵的列。
• 更新操作沒有原子性,即在更新過程中 select 結果很可能是一部分變了,一部分沒變,從上邊的具體過程就可以知道。
• 更新是按提交的順序執行的。
• 更新一旦提交,不能撤銷,即使重啟 Clickhouse 服務,也會繼續按照 system.mutations 的順序繼續執行。
• 已完成更新的條目不會立即刪除,保留條目的數量由 finished_mutations_to_keep 儲存引擎引數確定。超過資料量時舊的條目會被刪除。
• 更新可能會卡住,比如 update intvalue='abc ’這種型別錯誤的更新語句執行不過去,那麼會一直卡在這裡,此時,可以使用 KILL MUTATION 來取消。
使用建議
按照官方的說明, update/delete 的使用場景是一次更新大量資料,也就是 where 條件篩選的結果應該是一大片資料。
舉例: alter table test update status=1 where status=0 and day='2020-04-01' ,一次更新一天的資料。
那麼,能否一次只更新一條資料呢?例如: alter table test update pv=110 where id=100 當然也可以,但頻繁的這種操作,可能會對服務造成壓力。這很容易理解,如上文提到,更新的單位是分割槽,如果只更新一條資料,那麼需要重建一個分割槽;如果更新 100 條資料,而這 100 條可能落在 3 個分割槽上,則需重建 3 個分割槽;相對來說一次更新一批資料的整體效率遠高於一次更新一行。對於頻繁單條更新的這種場景,建議使用 ReplacingMergeTree 引擎來變相解決。具體如何使用,以後有時間再整理。
Hbase 隨機讀寫,但是 Hbase 的 update 操作不是真的 update ,它的實際操作是 insert 一條新的資料,打上不同的 timestamp ,而老的資料會在有效期之後自動刪除。而 Clickhouse 乾脆就不支援 update 和 delete 。
ClickHouse核心涉及模組
1. Column 與 Field
Column 和 Field 是 ClickHouse 資料最基礎的對映單元。作為一款百分之百的列式儲存資料庫, ClickHouse 按列儲存資料,記憶體中的一列資料由一個 Column 物件表示。 Column 物件分為介面和實現兩個部分,在 IColumn 介面物件中,定義了對資料進行各種關係運算的方法,例如插入資料的 insertRangeFrom 和 insertFrom 方法、用於分頁的 cut ,以及用於過濾的 filter 方法等。而這些方法的具體實現物件則根據資料型別的不同,由相應的物件實現,例如 ColumnString 、 ColumnArray 和 ColumnTuple 等。在大多數場合, ClickHouse 都會以整列的方式操作資料,但凡事也有例外。如果需要操作單個具體的數值 ( 也就是單列中的一行資料 ) ,則需要使用 Field 物件, Field 物件代表一個單值。與 Column 物件的泛化設計思路不同, Field 物件使用了聚合的設計模式。在 Field 物件內部聚合了 Null 、 UInt64 、 String 和 Array 等 13 種資料型別及相應的處理邏輯。
2. DataType
資料的序列化和反序列化工作由 DataType 負責。 IDataType 介面定義了許多正反序列化的方法,它們成對出現,例如 serializeBinary 和 deserializeBinary 、 serializeTextJSON 和 deserializeTextJSON 等,涵蓋了常用的二進位制、文字、 JSON 、 XML 、 CSV 和 Protobuf 等多種格式型別。 IDataType 也使用了泛化的設計模式,具體方法的實現邏輯由對應資料型別的例項承載,例如 DataTypeString 、 DataTypeArray 及 DataTypeTuple 等。
DataType 雖然負責序列化相關工作,但它並不直接負責資料的讀取,而是轉由從 Column 或 Field 物件獲取。在 DataType 的實現類中,聚合了相應資料型別的 Column 物件和 Field 物件。例如, DataTypeString 會引用字串型別的 ColumnString ,而 DataTypeArray 則會引用陣列型別的 ColumnArray ,以此類推。
3. Block 與 Block 流
ClickHouse 內部的資料操作是面向 Block 物件進行的,並且採用了流的形式。雖然 Column 和 Filed 組成了資料的基本對映單元,但對應到實際操作,它們還缺少了一些必要的資訊,比如資料的型別及列的名稱。於是 ClickHouse 設計了 Block 物件, Block 物件可以看作資料表的子集。 Block 物件的本質是由資料物件、資料型別和列名稱組成的三元組,即 Column 、 DataType 及列名稱字串。 Column 提供了資料的讀取能力,而 DataType 知道如何正反序列化,所以 Block 在這些物件的基礎之上實現了進一步的抽象和封裝,從而簡化了整個使用的過程,僅通過 Block 物件就能完成一系列的資料操作。在具體的實現過程中, Block 並沒有直接聚合 Column 和 DataType 物件,而是通過 ColumnWithTypeAndName 物件進行間接引用。
有了 Block 物件這一層封裝之後,對 Block 流的設計就是水到渠成的事情了。流操作有兩組頂層介面: IBlockInputStream 負責資料的讀取和關係運算, IBlockOutputStream 負責將資料輸出到下一環節。 Block 流也使用了泛化的設計模式,對資料的各種操作最終都會轉換成其中一種流的實現。 IBlockInputStream 介面定義了讀取資料的若干個 read 虛方法,而具體的實現邏輯則交由它的實現類來填充。
IBlockInputStream 介面總共有 60 多個實現類,它們涵蓋了 ClickHouse 資料攝取的方方面面。這些實現類大致可以分為三類:第一類用於處理資料定義的 DDL 操作,例如 DDLQueryStatusInputStream 等;第二類用於處理關係運算的相關操作,例如 LimitBlockInput-Stream 、 JoinBlockInputStream 及 AggregatingBlockInputStream 等;第三類則是與表引擎呼應,每一種表引擎都擁有與之對應的 BlockInputStream 實現,例如 MergeTreeBaseSelect-BlockInputStream ( MergeTree 表引擎 ) 、 TinyLogBlockInputStream ( TinyLog 表引擎 ) 及 KafkaBlockInputStream ( Kafka 表引擎 ) 等。
IBlockOutputStream 的設計與 IBlockInputStream 如出一轍。 IBlockOutputStream 介面同樣也定義了若干寫入資料的 write 虛方法。它的實現類比 IBlockInputStream 要少許多,一共只有 20 多種。這些實現類基本用於表引擎的相關處理,負責將資料寫入下一環節或者最終目的地,例如 MergeTreeBlockOutputStream 、 TinyLogBlockOutputStream 及 StorageFileBlock-OutputStream 等。
4. Table
在資料表的底層設計中並沒有所謂的 Table 物件,它直接使用 IStorage 介面指代資料表。表引擎是 ClickHouse 的一個顯著特性,不同的表引擎由不同的子類實現,例如 IStorageSystemOneBlock ( 系統表 ) 、 StorageMergeTree ( 合併樹表引擎 ) 和 StorageTinyLog ( 日誌表引擎 ) 等。 IStorage 介面定義了 DDL ( 如 ALTER 、 RENAME 、 OPTIMIZE 和 DROP 等 ) 、 read 和 write 方法,它們分別負責資料的定義、查詢與寫入。在資料查詢時, IStorage 負責根據 AST 查詢語句的指示要求,返回指定列的原始資料。後續對資料的進一步加工、計算和過濾,則會統一交由 Interpreter 直譯器物件處理。對 Table 發起的一次操作通常都會經歷這樣的過程,接收 AST 查詢語句,根據 AST 返回指定列的資料,之後再將資料交由 Interpreter 做進一步處理。
來源:http://www.cnblogs.com/ya-qiang/p/13680283.html
- Hive調優 | HiveServer2 效能優化與GC優化
- 資料湖Iceberg | 如何正確使用Iceberg
- 技術架構 應用場景揭祕,為什麼高斯Redis比開源香?
- 45歲程式設計師,精通各種技術體系,卻連個面試機會都沒有…
- OPPO大資料離線計算平臺架構演進
- 騰訊 Code Review 規範出爐!
- 一張圖,詳解大資料技術架構
- 雲原生大資料架構中實時計算維表和結果表的選型實踐
- 數倉出局,中臺已涼,資料湖稱王!
- 乾貨 | 再來聊一聊 Parquet 列式儲存格式
- 大公司上中臺,錢沒了...小公司上中臺,公司沒了
- 中國郵政郵科院 X DorisDB:統一OLAP平臺,大幅降低運維成本
- TiDB 實踐 | 當大資料架構遇上 TiDB
- 盤點Hadoop生態中 6 個核心的大資料元件
- (一)從程式設計師到架構師之技術專題
- 校招進大廠,分享 Tom哥的讀書單
- Spark 閉包(Task not serializable)問題分析及解決
- ClickHouse原理 | ClickHouse特性及底層儲存原理
- 史上第二全面的HBase讀寫效能優化總結
- 關於OLAP資料倉庫的歸納總結