表引擎
對于大多數正式的任務,應該使用MergeTree族中的引擎。
Clickhouse 中最強大的表引擎當屬 MergeTree (合并樹)引擎及該系列(*MergeTree)中的其他引擎。
日志引擎系列
這些引擎是為了需要寫入許多小數據量(少于一百萬行)的表的場景而開發的。
- StripeLog
- Log
- TinyLog
相同點:
- 數據存儲在磁盤上。
- 寫入時將數據追加在文件末尾。
- 不支持索引。
這意味著 SELECT 在范圍查詢時效率不高。 - 非原子地寫入數據。
如果某些事情破壞了寫操作,例如服務器的異常關閉,將會得到一張包含了損壞數據的表。
不同點:
- Log 引擎為表中的每一列使用不同的文件。并發讀取,寫入操作則阻塞讀取和其它寫入。Log 引擎適用于臨時數據,write-once 表以及測試或演示目的。
- StripeLog 將所有的數據存儲在一個文件中。
- TingLog 引擎不支持并行讀取和并發數據訪問,并將每一列存儲在不同的文件中。
StripeLog
#建表
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
column1_name [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
column2_name [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = StripeLog
StripeLog 引擎將所有列存儲在一個文件中。對每一次 Insert 請求,ClickHouse 將數據塊追加在表文件的末尾,逐列寫入。
ClickHouse 為每張表寫入以下文件:
- data.bin — 數據文件。
- index.mrk — 帶標記的文件。標記包含了已插入的每個數據塊中每列的偏移量。
StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。
帶標記的文件使得 ClickHouse 可以并行的讀取數據。這意味著 SELECT 請求返回行的順序是不可預測的。使用 ORDER BY 子句對行進行排序。
ClickHouse 在查詢數據時使用多線程。每個線程讀取單獨的數據塊并在完成后獨立的返回結果行。這樣的結果是,大多數情況下,輸出中塊的順序和輸入時相應塊的順序是不同的。
TinyLog
最簡單的表引擎,用于將數據存儲在磁盤上。每列都存儲在單獨的壓縮文件中。寫入時,數據將附加到文件末尾。不支持索引。
并發數據訪問不受任何限制: 如果同時從表中讀取并在不同的查詢中寫入,則讀取操作將拋出異常 。如果同時寫入多個查詢中的表,則數據將被破壞。
這種表引擎的典型用法是 write-once:首先只寫入一次數據,然后根據需要多次讀取。查詢在單個流中執行。換句話說,此引擎適用于相對較小的表(建議最多1,000,000行)。
特殊引擎
Memory
Memory 引擎以未壓縮的形式將數據存儲在內存中。數據完全以讀取時獲得的形式存儲。換句話說,從這張表中讀取是很輕松的。并發數據訪問是同步的。鎖范圍小:讀寫操作不會相互阻塞。不支持索引。閱讀是并行化的。
在簡單查詢上達到最大生產率(超過10 GB /秒),因為沒有磁盤讀取,不需要解壓縮或反序列化數據。(值得注意的是,在許多情況下,與 MergeTree 引擎的性能幾乎一樣高)。重新啟動服務器時,表中的數據消失,表將變為空。通常,使用此表引擎是不合理的。
Merge
Merge 引擎本身不存儲數據,但可用于同時從任意多個其他的表中讀取數據。 讀是自動并行的,不支持寫入。讀取時,那些被真正讀取到數據的表的索引(如果有的話)會被使用。
Merge 引擎的參數:一個數據庫名和一個用于匹配表名的正則表達式。
Merge(db, 'regex')
Merge 引擎的一個典型應用是可以像使用一張表一樣使用大量的 TinyLog 表。
Distributed
分布式引擎本身不存儲數據, 但可以在多個服務器上進行分布式查詢。 讀是自動并行的。讀取時,遠程服務器表的索引(如果有的話)會被使用。
分布式引擎參數:服務器配置文件中的集群名,遠程數據庫名,遠程表名,數據分片鍵(可選)。
Distributed(cluster, db, table[, sharding_key])
遠程服務器不僅用于讀取數據,還會對盡可能數據做部分處理。分片是指包含數據不同部分的服務器(要讀取所有數據,必須訪問所有分片)。 副本是存儲復制數據的服務器(要讀取所有數據,訪問任一副本上的數據即可)。配置了副本,讀取操作會從每個分片里選擇一個可用的副本。可配置負載平衡算法(挑選副本的方式)。 如果跟服務器的連接不可用,則在嘗試短超時的重連。如果重連失敗,則選擇下一個副本,依此類推。如果跟所有副本的連接嘗試都失敗,則嘗試用相同的方式再重復幾次。 該機制有利于系統可用性,但不保證完全容錯:如有遠程服務器能夠接受連接,但無法正常工作或狀況不佳。
合并樹引擎系列
MergeTree
MergeTree 引擎系列的基本理念如下:當有巨量數據要插入到表中時,需要高效地一批批寫入數據片段,并希望這些數據片段在后臺按照一定規則合并。
應對表的并發訪問,我們使用多版本機制。換言之,當同時讀和更新表時,數據從當前查詢到的一組片段中讀取。沒有冗長的的鎖。插入不會阻礙讀取。對表的讀操作是自動并行的。
特點
- 存儲的數據按主鍵排序。
- 允許使用分區(在指定了主鍵的情況下)。查詢中指定了分區鍵時 ClickHouse 會自動截取分區數據。這也有效增加了查詢性能。
- 支持數據副本。
- 支持數據采樣。
#建表
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]
存儲
表由按主鍵排序的數據片段組成。
當數據被插入到表中時,會分成數據片段并按主鍵的字典序排序。
不同分區的數據會被分成不同的片段,ClickHouse 在后臺合并數據片段以便更高效存儲。不會合并來自不同分區的數據片段。這個合并機制并不保證相同主鍵的所有行都會合并到同一個數據片段中。
主鍵與排序鍵
- 稀疏索引讓你能操作有巨量行的表。因為這些索引是常駐內存(RAM)的。
- ClickHouse 不要求主鍵惟一。所以,你可以插入多條具有相同主鍵的行。
- 主鍵中列的數量并沒有明確的限制。
- 長的主鍵會對插入性能和內存消耗有負面影響。
- 默認情況下主鍵跟排序鍵相同。指定一個跟排序鍵(用于排序數據片段中行的表達式) 不一樣的主鍵(用于計算寫到索引文件的每個標記值的表達式)是可以的。 這種情況下,主鍵表達式元組必須是排序鍵表達式元組的一個前綴。
ReplacingMergeTree
ENGINE = ReplacingMergeTree([ver])
該引擎和MergeTree的不同之處在于它會刪除具有相同主鍵的重復項。
數據的去重只會在合并的過程中出現。合并會在未知的時間在后臺進行,因此你無法預先作出計劃。有一些數據可能仍未被處理。盡管你可以調用 OPTIMIZE 語句發起計劃外的合并,但請不要指望使用它,因為 OPTIMIZE 語句會引發對大量數據的讀和寫。
因此,ReplacingMergeTree 適用于在后臺清除重復的數據以節省空間,但是它不保證沒有重復的數據出現。
并的時候,ReplacingMergeTree 從所有具有相同主鍵的行中選擇一行留下: 如果 ver 列未指定,選擇最后一條。 如果 ver 列已指定,選擇 ver 值最大的版本。