第4章 表引擎

表引擎(即表的類型)決定了:
1)數據的存儲方式和位置,寫到哪里以及從哪里讀取數據
2)支持哪些查詢以及如何支持。
3)并發數據訪問。
4)索引的使用(如果存在)。
5)是否可以執行多線程請求。
6)數據復制參數。
ClickHouse的表引擎有很多,下面介紹其中幾種,對其他引擎有興趣的可以去查閱官方文檔:https://clickhouse.yandex/docs/zh/operations/table_engines/

4.1 TinyLog

最簡單的表引擎,用于將數據存儲在磁盤上。每列都存儲在單獨的壓縮文件中,寫入時,數據將附加到文件末尾。
該引擎沒有并發控制

  • 如果同時從表中讀取和寫入數據,則讀取操作將拋出異常;
  • 如果同時寫入多個查詢中的表,則數據將被破壞。
    這種表引擎的典型用法是 write-once:首先只寫入一次數據,然后根據需要多次讀取。此引擎適用于相對較小的表(建議最多1,000,000行)。如果有許多小表,則使用此表引擎是適合的,因為它比需要打開的文件更少。當擁有大量小表時,可能會導致性能低下。 不支持索引。
    案例:創建一個TinyLog引擎的表并插入一條數據
:)create table t (a UInt16, b String) ENGINE=TinyLog;
:)insert into t (a, b) values (1, 'abc');

此時我們到保存數據的目錄/var/lib/clickhouse/data/default/t中可以看到如下目錄結構:

[root@hadoop102 t]# ls
a.bin  b.bin  sizes.json

a.bin 和 b.bin 是壓縮過的對應的列的數據, sizes.json 中記錄了每個 *.bin 文件的大?。?/p>

[root@hadoop102 t]# cat sizes.json 
{"yandex":{"a%2Ebin":{"size":"28"},"b%2Ebin":{"size":"30"}}}

4.2 Memory

內存引擎,數據以未壓縮的原始形式直接保存在內存當中,服務器重啟數據就會消失。讀寫操作不會相互阻塞,不支持索引。簡單查詢下有非常非常高的性能表現(超過10G/s)。
一般用到它的地方不多,除了用來測試,就是在需要非常高的性能,同時數據量又不太大(上限大概 1 億行)的場景。

4.3 Merge

Merge 引擎 (不要跟 MergeTree 引擎混淆) 本身不存儲數據,但可用于同時從任意多個其他的表中讀取數據。 讀是自動并行的,不支持寫入。讀取時,那些被真正讀取到數據的表的索引(如果有的話)會被使用。
Merge 引擎的參數:一個數據庫名和一個用于匹配表名的正則表達式。
案例:先建t1,t2,t3三個表,然后用 Merge 引擎的 t 表再把它們鏈接起來。

:)create table t1 (id UInt16, name String) ENGINE=TinyLog;
:)create table t2 (id UInt16, name String) ENGINE=TinyLog;
:)create table t3 (id UInt16, name String) ENGINE=TinyLog;

:)insert into t1(id, name) values (1, 'first');
:)insert into t2(id, name) values (2, 'second');
:)insert into t3(id, name) values (3, 'i am in t3');

:)create table t (id UInt16, name String)
ENGINE=Merge(currentDatabase(), '^t');

:) select * from t;
┌─id─┬─name─┐
│  2 │ second │
└────┴──────┘
┌─id─┬─name──┐
│  1 │ first │
└────┴───────┘
┌─id─┬─name───────┐
│ 3  │ i am in t3 │
└────┴────────────┘

4.4 MergeTree

Clickhouse 中最強大的表引擎當屬 MergeTree (合并樹)引擎及該系列(*MergeTree)中的其他引擎。
MergeTree 引擎系列的基本理念如下。當你有巨量數據要插入到表中,你要高效地一批批寫入數據片段,并希望這些數據片段在后臺按照一定規則合并。相比在插入時不斷修改(重寫)數據進存儲,這種策略會高效很多。

image.png
image.png

格式:
ENGINE [=] MergeTree(date-column [, sampling_expression], (primary, key), index_granularity)
參數解讀:
date-column — 類型為 Date 的列名。ClickHouse 會自動依據這個列按月創建分區。分區名格式為 "YYYYMM" 。
sampling_expression — 采樣表達式。
(primary, key) — 主鍵。類型為Tuple()
index_granularity — 索引粒度。即索引中相鄰”標記”間的數據行數。設為 8192 可以適用大部分場景。
案例:

create table mt_table (date  Date, id UInt8, name String) ENGINE=MergeTree()
partition by date 
order by  (id, name)
settings index_granularity=8192;

insert into mt_table values ('2019-05-01', 1, 'zhangsan');
insert into mt_table values ('2019-06-01', 2, 'lisi');
insert into mt_table values ('2019-05-03', 3, 'wangwu');

在/var/lib/clickhouse/data/default/mt_tree下可以看到:

[root@hadoop102 mt_table]# ls
20190501_20190501_2_2_0  
20190503_20190503_6_6_0  
20190601_20190601_4_4_0  
detached

隨便進入一個目錄:

[root@hadoop102 20190601_20190601_4_4_0]# ls
checksums.txt  columns.txt  date.bin  date.mrk  id.bin  id.mrk  name.bin  name.mrk  primary.idx
  • *.bin是按列保存數據的文件
  • *.mrk保存塊偏移量
  • primary.idx保存主鍵索引

4.5 ReplacingMergeTree

這個引擎是在 MergeTree 的基礎上,添加了“處理重復數據”的功能,該引擎和MergeTree的不同之處在于它會刪除具有相同主鍵的重復項。數據的去重只會在合并的過程中出現。合并會在未知的時間在后臺進行,所以你無法預先作出計劃。有一些數據可能仍未被處理。因此,ReplacingMergeTree 適用于在后臺清除重復的數據以節省空間,但是它不保證沒有重復的數據出現。
格式:
ENGINE [=] ReplacingMergeTree(date-column [, sampling_expression], (primary, key), index_granularity, [ver])
可以看出他比MergeTree只多了一個ver,這個ver指代版本列。
案例:

create table rmt_table (date  Date, id UInt8, name String,point UInt8) ENGINE= ReplacingMergeTree(date, (id, name), 8192,point);

插入一些數據:

insert into rmt_table values ('2019-07-10', 1, 'a', 20);
insert into rmt_table values ('2019-07-10', 1, 'a', 30);
insert into rmt_table values ('2019-07-11', 1, 'a', 20);
insert into rmt_table values ('2019-07-11', 1, 'a', 30);
insert into rmt_table values ('2019-07-11', 1, 'a', 10);

等待一段時間或optimize table rmt_table手動觸發merge,后查詢

:) select * from rmt_table;
┌───────date─┬─id─┬─name─┬─point─┐
│ 2019-07-11 │  1 │ a    │    30 │
└────────────┴────┴──────┴───────┘

4.6 SummingMergeTree

該引擎繼承自 MergeTree。區別在于,當合并 SummingMergeTree 表的數據片段時,ClickHouse 會把所有具有相同主鍵的行合并為一行,該行包含了被合并的行中具有數值數據類型的列的匯總值。如果主鍵的組合方式使得單個鍵值對應于大量的行,則可以顯著的減少存儲空間并加快數據查詢的速度,對于不可加的列,會取一個最先出現的值。
語法:
ENGINE [=] SummingMergeTree(date-column [, sampling_expression],
(primary, key), index_granularity, [columns])
columns — 包含將要被匯總的列的列名的元組
案例:

create table smt_table (date Date, name String, a UInt16, b UInt16) ENGINE=SummingMergeTree(date, (date, name), 8192, (a))

插入數據:

insert into smt_table (date, name, a, b) values ('2019-07-10', 'a', 1, 2);
insert into smt_table (date, name, a, b) values ('2019-07-10', 'b', 2, 1);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'a', 3, 1);
insert into smt_table (date, name, a, b) values ('2019-07-12', 'c', 1, 3);

等待一段時間或optimize table smt_table手動觸發merge,后查詢

:) select * from smt_table 

┌───────date─┬─name─┬─a─┬─b─┐
│ 2019-07-10 │ a    │ 1 │ 2 │
│ 2019-07-10 │ b    │ 2 │ 1 │
│ 2019-07-11 │ a    │ 3 │ 1 │
│ 2019-07-11 │ b    │ 6 │ 8 │
│ 2019-07-12 │ c    │ 1 │ 3 │
└────────────┴──────┴───┴───┘

發現2019-07-11,b的a列合并相加了,b列取了8(因為b列為8的數據最先插入)。

4.7 Distributed

分布式引擎,本身不存儲數據, 但可以在多個服務器上進行分布式查詢。 讀是自動并行的。讀取時,遠程服務器表的索引(如果有的話)會被使用。
Distributed(cluster_name, database, table [, sharding_key])
參數解析:
cluster_name - 服務器配置文件中的集群名,在/etc/metrika.xml中配置的
database – 數據庫名
table – 表名
sharding_key – 數據分片鍵
案例演示:

1)在hadoop102,hadoop103,hadoop104上分別創建一個表t

:) create table t(id UInt16, name String) ENGINE=TinyLog;

2)在三臺機器的t表中插入一些數據

 insert into t(id, name) values (1, 'zhangsan');
 insert into t(id, name) values (2, 'lisi');

3)在hadoop102上創建分布式表

:) create table dis_table(id UInt16, name String) ENGINE=Distributed(clickhouse_cluser, default, t, id);

clickhouse_cluser
4)往dis_table中插入數據

:) insert into dis_table select * from t
image.png

5)查看數據量

:) select count() from dis_table 
FROM dis_table 

┌─count()─┐
│       8 │
└─────────┘
:) select count() from t

SELECT count()
FROM t 

┌─count()─┐
│       3 │
└─────────┘

可以看到每個節點大約有1/3的數據

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容