ClickHouse介绍安装和工作原理(1)
ClickHouse介紹
? ? ?ClickHouse 是一個用于聯機分析 (OLAP) 的列式數據庫管理系統 (DBMS)。
? ? ?ClickHouse 官網:https://clickhouse.tech/,它具有 ROLAP、在線實時查詢、完整的 DBMS 功能支持、列式存儲、不需要任何數據預處理、支持批量更新、擁有非常完善的 SQL 支持和函數、支持高可用、不依賴 Hadoop 復雜生態、開箱即用等許多特點。 在 1 億數據集體量的情況下,ClickHouse 的平均響應速度是 Vertica 的 2.63 倍、InfiniDB 的 17 倍、MonetDB 的 27 倍、Hive 的 126 倍、MySQL 的 429 倍以及Greenplum 的 10 倍。詳細的測試結果可以查閱:https://clickhouse.tech/benchmark/dbms/。
? ? ??ClickHouse 缺點:
1、沒有完整的事務支持 2、稀疏索引導致 ClickHouse 不擅長細粒度或者 key-value 類型數據的查詢需求 3、缺少高頻率,低延遲的修改或刪除已存在數據的能力。僅能用于批量刪除或修改數據 4、不擅長 join 操作ClickHouse 設計思路剖析
? ? ? ?關于 OLTP 系統和 OLAP 系統的核心設計思想和技術路線有哪些呢?我們做一個完整的探討。? ? ? ? ?
? ? ? ?數據存儲系統的關于查詢的典型操作:
-- 第一種需求: 根據 key 找 value select name, age from student where id = 1; select name, age from student where age > 30;-- 第二種需求: 根據 department 統計平均年齡 select department, avg(age) from student group by department;如果:第一種需求多
如果數據量小,并且數據是結構化的,使用 MySQL 去存儲即可 如果數據量大,不管是不是結構化的,可以轉成 key-value 的存儲,使用 HBase,Cassandra 等來解決如果:第二種需求多:
如果數據量小,并且數據是結構化的,使用 MySQL 去存儲即可 如果數據量大,不管是不是結構化的,設計一個專門用來做分析的存儲計算引擎解決分析的低效率問題關于如何設計一個 HBase 存儲系統,我們探討一下它的核心設計思想:
01、內存 + 磁盤:保證處理效率,也保證數據安全 02、內存:必須經過設計,內存具備優秀的數據結構,保證基本的讀寫高效,甚至為了不同的需求,可以讓讀寫效率傾斜。 03、磁盤:數據必須存放在磁盤,保證數據安全。磁盤數據文件必須經過精心設計,保證掃描磁盤數據文件的高效率 04、數據排序:在海量數據中要想保證低延時的隨機讀寫操作,數據最好是排序的 05、范圍分區:當數據排序之后,可以進行范圍分區,來平攤負載,讓多臺服務器聯合起來對外提供服務 06、跳表:基于數據排序+范圍分區構建索引表,形成跳表的拓撲結構,方便用戶操作時快速定位數據分區的位置 07、LSM-Tree存儲引擎:把隨機寫變成順序追加,在通過定期合并的方式來合并數據,去除無效數據,從而實現數據的刪除和修改。? ? ? ?海量數據中,如果進行高效率的查詢的核心思想:設計一種架構,能夠快速把待搜尋的數據范圍降低到原來的 1/n,然后再結合索引或者熱點數據放在內 存等思路,就能實現高效率的查詢了。 那么一個專門用來做 OLAP 分析的存儲引擎該如何設計呢?如何在海量數據中,針對大量數據進行查詢分析呢?一些常見的方案和手段如下:
01、列式存儲 + 字段類型統一 02、列裁剪 03、數據排序 04、數據分區分片 + 分布式查詢 05、預聚合 06、利用CPU特性:向量化引擎,操作系統必須支持 07、主鍵索引+二級索引+位圖索引+布隆索引等 08、支持近似計算 pv 09、定制引擎:多樣化的存儲引擎滿足不同場景的特定需要 10、多樣化算法選擇:Volnitsky高效字符串搜索算法 和 HyperLogLog基于概率高效去重算法? ? ??總結一下:單條記錄的增刪改等操作,通過數據的橫向劃分,做到數據操作的快速定位,在海量數據查詢分析中,一般就是針對某些列做分析,既然并不 是全部列,那么把數據做縱向切分把表中的數據按照列來單獨存儲,那么在做分析的時候,同樣可以快速把待查詢分析的數據總量降低到原來表的1/n, 同樣提高效率。 提到預聚合,大家會想到 Kylin,但是 Kylin 也有它的缺點:
1、預聚合只支持固定的分析場景,無法滿足自定義分析場景,所以預聚合只能作為一種可選方案 2、維度組合爆炸會導致數據膨脹,這樣會造成不必要的計算和存儲開銷。無必要的維度組合的計算就屬于浪費資源 3、大概率數據都是增量生成,預聚合不能進行數據更新。所以會產生大量的重算ClickHouse 安裝部署
? ? ? ? ClickHouse 可以通過源碼編譯、預編譯壓縮包、Docker 鏡像和 RPM 等多種方法進行安裝,在此講解 RPM 方式的安裝,先從這兒下載 相關的 RPM 包: https://packagecloud.io/altinity/clickhouse
ClickHouse 表引擎介紹
? ? ? ?表引擎在 ClickHouse 中的作用十分關鍵,直接決定了數據如何存儲和讀取、是否支持并發讀寫、是否支持 index、支持的 query 種類、是否支持主備復 制等。
1、數據的存儲方式和位置,寫到哪里以及從哪里讀取數據 2、支持哪些查詢以及如何支持。 3、并發數據訪問。 4、索引的使用(如果存在)。 5、是否可以執行多線程請求。 6、數據復制參數。? ? ? ?具體可看官網:https://clickhouse.tech/docs/zh/engines/table-engines/ 關于 ClickHouse 的底層引擎,其實可以分為 數據庫引擎 和 表引擎 兩種。在此,我們重點講解 表引擎。 關于庫引擎,? ? ? ? 簡單總結一下:ClickHouse 也支持在創建庫的時候,指定庫引擎,目前支持5種,分別是:Ordinary,Dictionary, Memory, Lazy, MySQL,其實 Ordinary 是默認庫引擎,在此類型庫引擎下,可以使用任意類型的表引擎。
1、Ordinary引擎:默認引擎,如果不指定數據庫引擎創建的就是 Ordinary 數據庫 2、Dictionary引擎:此數據庫會自動為所有數據字典創建表 3、Memory引擎:所有數據只會保存在內存中,服務重啟數據消失,該數據庫引擎只能夠創建 Memory 引擎表 4、MySQL引擎:改引擎會自動拉取遠端 MySQL 中的數據,并在該庫下創建 MySQL 表引擎的數據表 5、Lazy延時引擎:在距最近一次訪問間隔 expiration_time_in_seconds 時間段內,將表保存在內存中,僅適用于 Log 引擎表? ? ? ??ClickHouse 的表引擎提供了四個系列(Log、MergeTree、Integration、Special)大約 28 種表引擎,各有各的用途。比如 Log 系列用來做小表數據分析,MergeTree 系列用來做大數據量分析,而 Integration 系列則多用于外表數據集成。Log、Special、Integration 系列的表引擎相對來說,應用場景 有限,功能簡單,應用特殊用途,MergeTree 系列表引擎又和兩種特殊表引擎(Replicated,Distributed)正交形成多種具備不同功能的 MergeTree 表 引擎。
MergeTree 引擎工作機制詳解
? ? ? ?MergeTree 系列是官方主推的存儲引擎,支持幾乎所有 ClickHouse 核心功能,該系列中,常用的表引擎有:MergeTree、ReplacingMergeTree、 CollapsingMergeTree、VersionedCollapsingMergeTree、SummingMergeTree、AggregatingMergeTree 等。學習好 MergeTree 表引擎的工作機 制,是應用好 ClickHouse 的最基本基礎。
關于表引擎類型:
? ? ? ?第一:MergeTree 表引擎主要用于海量數據分析,支持數據分區、存儲有序、主鍵索引、稀疏索引、數據 TTL 等。MergeTree 支持所有 ClickHouse SQL 語法,但是有些功能與 MySQL 并不一致,比如在 MergeTree 中主鍵并不用于去重。
? ? ? ? 第二:為了解決 MergeTree 相同主鍵無法去重的問題,ClickHouse 提供了 ReplacingMergeTree 引擎,用來做去重。ReplacingMergeTree 確保數據 最終被去重,但是無法保證查詢過程中主鍵不重復。因為相同主鍵的數據可能被 shard 到不同的節點,但是 compaction 只能在一個節點中進行,而且 optimize 的時機也不確定。
? ? ? ? ?第三:CollapsingMergeTree 引擎要求在建表語句中指定一個標記列 Sign(插入的時候指定為 1,刪除的時候指定為 -1),后臺 Compaction 時會將主 鍵相同、Sign 相反的行進行折疊,也即刪除。來消除 ReplacingMergeTree 的限制。
? ? ? ? 第四:為了解決 CollapsingMergeTree 亂序寫入情況下無法正常折疊問題,VersionedCollapsingMergeTree 表引擎在建表語句中新增了一列 Version,用于在亂序情況下記錄狀態行與取消行的對應關系。主鍵相同,且 Version 相同、Sign 相反的行,在 Compaction 時會被刪除。
? ? ? ? 第五:ClickHouse 通過 SummingMergeTree 來支持對主鍵列進行預先聚合。在后臺 Compaction 時,會將主鍵相同的多行進行 sum 求和,然后使用 一行數據取而代之,從而大幅度降低存儲空間占用,提升聚合計算性能。
? ? ? ? 第六:AggregatingMergeTree 也是預先聚合引擎的一種,用于提升聚合計算的性能。與 SummingMergeTree 的區別在于:SummingMergeTree 對 非主鍵列進行 sum 聚合,而 AggregatingMergeTree 則可以指定各種聚合函數。
MergeTree 的建表語法:
CREATE TABLE [IF NOT EXISTS] [db_name.]table_name ( name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr], name2 [type] [DEFAUErEMAMLERLALLIZED|ALIAS expr], 省略... ) ENGINE = MergeTree() [PARTITION BY expr] [ORDER BY expr] [PRIMARY KEY expr] [SAMPLE BY expr] [SETTINGS name=value, 省略...]?介紹一下其中的幾個關鍵選項:
1、PARTITION BY:分區鍵。指定表數據以何種標準進行分區。分區鍵既可以是單個列字段,也可以通過元組的形式使用多個列字段,同時它也支持使用列表達式。 2、ORDER BY:排序鍵,用于指定在一個數據片段內,數據以何種標準排序。默認情況下主鍵(PRIMARY KEY)與排序鍵相同。 3、PRIMARY KEY:主鍵。聲明后會依照主鍵字段生成一級索引。默認情況下,主鍵與排序鍵(ORDER BY)相同,所以通常直接使用 ORDER BY 代為指定主鍵。 4、SETTINGS:index_granularity 選項表示索引的粒度,默認值為 8192。MergeTree 索引在默認情況下,每間隔 8192 行數據才生成一條索引。 5、SAMPLE BY:抽樣表達式,用于聲明數據以何種標準進行采樣。注意 settings 中的重要參數:
1、index_granularity 默認是 8192 2、index_granularity_bytes 默認 10M,需要通過 enable_mixed_granularity_parts 來開啟?ClickHouse 工作原理
? ? ? ?MergeTree 表引擎的內部工作細節!最終就是告訴你:為什么 clickhouse 做查詢分析,那么快?
? ? ? ? ClickHouse 從 OLAP 場景需求出發,定制開發了一套全新的高效列式存儲引擎,并且實現了數據有序存儲、主鍵索引、稀疏索引、數據 Sharding、數據 Partitioning、TTL、主備復制等豐富功能。這些功能共同為 ClickHouse 極速的分析性能奠定了基礎。
?數據分區
? ? ? 關于表分區目錄結構:MergeTree 表的分區目錄物理結構:
?關于這些文件的解釋:
1、分區目錄:20190710_20190711_1_5_1,一個分區可能會有多個不同的目錄,該目錄下存儲該分區的數據及其他各種形式的數據。后臺會執行合并,把相同分區的多個目錄合并到一個分區。 2、checksums.txt:校驗文件。使用二進制格式存儲。它保存了余下各類文件(primary.idx、count.txt等)的 size 大小及 size 的哈希值,用于快速校驗文件的完整性和正確性。 3、columns.txt:列信息文件,使用明文格式存儲。用于保存此數據分區下的列字段信息 4、count.txt:計數文件,使用明文格式存儲。用于記錄當前數據分區目錄下數據的總行數 5、primary.idx:一級索引文件,主鍵索引文件 6、xxx.bin:數據文件,使用壓縮格式存儲,默認為 LZ4 壓縮格式,用于存儲某一列的數據,每一列都對應一個該文件,如列 date 為 date.bin 7、xxx.mrk2:列字段標記文件,如果使用了自適應大小的索引間隔,則標記文件以 .mrk2 命名,否則以 .mrk 命名。它建立 primary.idx 稀疏索引與xxx.bin 數據文件之間的映射關系,先通過主鍵索引找到數據的偏移量,然后去 xxx.bin 數據文件中找到真實數據 8、... 還有二級索引 和 分區鍵相關信息文件等等關于表分區命名規則:分區的命名規則:PartitionID_MinBlockNum_MaxBlockNum_Level
? ? ? ?該 blocknum 在該表內全局累加,每次創建一個新的分區目錄的時候,就會累加 1。Level 是分區被合并過的次數計數,合并一次則加1。 關于分區的合并規則:
?
列式存儲
?一級索引
? ? ? ?關于一級索引:MergeTree 的主鍵使用 PRIMARY KEY 定義,待主鍵定義之后,MergeTree 會依據 index_granularity 間隔(默認 8192 行),為數據表 生成一級索引并保存至 primary.idx 文件內。一級索引是稀疏索引,意思就是說:每一段數據生成一條索引記錄,而不是每一條數據都生成索引,如果是 每一條數據都生成索引,則是稠密索引。稀疏索引的好處,就是少量的索引標記,就能記錄大量的數據區間位置信息,比如不到 24414 條標記信息,就 能為 2E 條數據提供索引(算法:200000000 / 8192)。在 ClickHouse 中,一級索引常駐內存。總的來說:一級索引和標記文件一一對齊,兩個索引標 記之間的數據,就是一個數據區間,在數據文件中,這個數據區間的所有數據,生成一個壓縮數據塊
?
? ? ? ?需要注意的是:ClickHouse 的主鍵索引與 MySQL 等數據庫不同,它并不用于去重,即便 primary key 相同的行,也可以同時存在于數據庫中。要想實 現去重效果,需要結合具體的表引擎 ReplacingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree 實現。這個在之前的表引擎介紹 中講過。
二級索引
? ? ? ?關于二級索引:又稱之為跳數索引。目的和一級索引一樣,是為了減少待搜尋的數據的范圍。跳數索引的默認是關閉的,需要通過 SET allow_experimental_data_skipping_indices = 1 來開啟,索引生成粒度由 granularity 控制,如果生成了二級索引,則會在分區目錄下生成額外 的:skp_idx_[Column].idx 與 skp_idx_[Column].mrk 文件。跳數索引的生成規則:按照特定規則每隔 granularity 個 index_granularity 條數據,就會 生成一條跳數索引。比如 minmax 跳數索引,生成的是:granularity 個 index_granularity 條數據內的最大值最小值生成一條索引,如果將來需要針對 構建二級索引的這個字段求最大值最小值,則可以幫助提高效率。跳數索引一共支持四種類型:minmax(最大最小)、set(去重集合)、 ngrambf_v1(ngram分詞布隆索引) 和 tokenbf_v1(標點符號分詞布隆索引),一張數據表支持同時聲明多個跳數索引。比如:
GRANULARITY = 你在創建二級索引索引的指定的 INDEX_GRANULARITY = 8192 GRANULARITY * INDEX_GRANULARITY CREATE TABLE skip_test( ID String, URL String, Code String, EventTime Date, INDEX a ID TYPE minmax GRANULARITY 5, INDEX b (length(ID) * 8) TYPE set(2) GRANULARITY 5, INDEX c (ID, Code) TYPE ngrambf_v1(3, 256, 2, O) GRANULARITY 5, INDEX d ID TYPE tokenbf_v1(256, 2, 0) GRANULARITY 5 ) ENGINE= MergeTree() order by id;關于跳數索引支持的多種類型的區別:
1、minmax:以 index_granularity 為單位,存儲指定表達式計算后的 min、max 值;在等值和范圍查詢中能夠幫助快速跳過不滿足要求的塊,減少IO。 2、set(max_rows):以index granularity為單位,存儲指定表達式的 distinct value 集合,用于快速判斷等值查詢是否命中該塊,減少IO。 3、ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):將 string 進行 ngram 分詞后,構建 bloom filter,能夠優化 等值、like、in 等查詢條件。 4、tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):與 ngrambf_v1 類似,區別是不使用 ngram 進行分詞,而是通過標點符號進行詞語分割。 5、bloom_filter([false_positive]):對指定列構建 bloom filter,用于加速 等值、like、in 等查詢條件的執行。數據壓縮
? ? ? ? 關于數據壓縮:ClickHouse 的數據存儲文件 column.bin 中存儲是一列的數據,由于一列是相同類型的數據,所以方便高效壓縮。在進行壓縮的時候,請 注意:一個壓縮數據塊由頭信息和壓縮數據兩部分組成,頭信息固定使用 9 位字節表示,具體由 1 個 UInt8(1字節)整型和 2 個 UInt32(4字節)整型 組成,分別代表使用的壓縮算法類型、壓縮后的數據大小和壓縮前的數據大小。每個壓縮數據塊的體積,按照其壓縮前的數據字節大小,都被嚴格控制在 64KB~1MB,其上下限分別由 min_compress_block_size(默認65536=64KB)與 max_compress_block_size(默認1048576=1M)參數指定。具體壓 縮規則:
? ? ? ?原理的說法:每 8192 條記錄,其實就是一條一級索引 一個索引區間 壓縮成一個數據塊。自適應壓縮?
如果: a = 10kb b = 你的一個8192條數據的大小 c = 1M 1、單個批次數據 size < 64KB:如果單個批次數據小于 64KB,則繼續獲取下一批數據,直至累積到size >= 64KB時,生成下一個壓縮數據塊。如果平均每條 記錄小于8byte,多個數據批次壓縮成一個數據塊 2、單個批次數據 64KB<= size <=1MB:如果單個批次數據大小恰好在 64KB 與 1MB 之間,則直接生成下一個壓縮數據塊。 3、單個批次數據 size > 1MB:如果單個批次數據直接超過 1MB,則首先按照 1MB大小截斷并生成下一個壓縮數據塊。剩余數據繼續依照上述規則執行。此時,會出現一個批次數據生成多個壓縮數據塊的情況。如果平均每條記錄的大小超過 128byte,則會把當前這一個批次的數據壓縮成多個數據塊?
?
總結:在一個 xxx.bin 字段存儲文件中,并不是一個壓縮塊對應到一條一級索引! 總結:一個 [Column].bin 其實是由一個個的壓縮數據塊組成的。每個壓縮塊的大小在:64kb - 1M 之間。?
?數據標記
? ? ? ?關于數據標記:數據標記文件也與 .bin 文件一一對應。即每一個列字段 [Column].bin 文件都有一個與之對應的 [Column].mrk2 數據標記文件,用于記 錄數據在 .bin 文件中的偏移量信息。一行標記數據使用一個元組表示,元組內包含兩個整型數值的偏移量信息。它們分別表示在此段數據區間內,在對 應的 .bin 壓縮文件中,壓縮數據塊的起始偏移量;以及將該數據壓縮塊解壓后,其未壓縮數據的起始偏移量。每一行標記數據都表示了一個片段的數據 (默認8192行)在 .bin 壓縮文件中的讀取位置信息。標記數據與一級索引數據不同,它并不能常駐內存,而是使用 LRU(最近最少使用)緩存策略加快 其取用速度。
查詢數據
select name from student where date = 201905;? ? ? ? ? 指定分區 ==> 指定字段(xxx.bin )==> 根據一級索引(primary.idx)定位到 標記文件(name.mrk2)中的那一條記錄 ==> 掃描對應字段的 mark 標記文件 獲取兩個偏移量信息(當前要查找的數據,處于這個 .bin 數據文件中的那個 壓縮數據塊,這個壓縮數據塊在 .bin 文件的偏移量, 這個壓縮數據塊解壓縮 出來之后,要找的數據在當前這個壓縮數據快的偏移量) ==> 根據第一個偏移量去 .bin 文件中定位到一個 壓縮數據快 ==> 讀取數據到內存執行解壓縮 ==> 根據第二個偏移量去內存解壓縮數據中找到對應的數據 關于分區 關于一級索引 關于二級索引 關于數據壓縮 關于數據標記 提高數據查詢效率的核心原則只有一個:誰做的輔助動作能快速的幫助我們去快速降低待搜尋的數據范圍 分布式系統的核心思想:分而治之,必須提供一套架構方便用戶的請求被快速的定位到某個單臺服務器去處理。一般來說,這個服務器處理這個請求,都 是很快的!
總結
以上是生活随笔為你收集整理的ClickHouse介绍安装和工作原理(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2.12-3.20上周的习惯坚持下来了✌
- 下一篇: 一沙一世界,一叶一菩提