表引擎(即表的類型)決定了:linux
- 數據的存儲方式和位置,寫到哪裏以及從哪裏讀取數據
- 支持哪些查詢以及如何支持。
- 併發數據訪問。
- 索引的使用(若是存在)。
- 是否能夠執行多線程請求。
- 數據複製參數。
在讀取時,引擎只須要輸出所請求的列,但在某些狀況下,引擎能夠在響應請求時部分處理數據。對於大多數正式的任務,應該使用MergeTree族中的引擎。sql
1 日誌系列
具備最小功能的輕量級引擎。當您須要快速寫入許多小表(最多約100萬行)並在之後總體讀取它們時,該類型的引擎是最有效的。json
1.1 StripeLog
在你須要寫入許多小數據量(小於一百萬行)的表的場景下使用這個引擎。安全
-- 建表 CREATE TABLE stripe_log_table( timestamp DateTime, message_type String, message String)ENGINE = StripeLog ; -- 插入數據 INSERT INTO stripe_log_table VALUES (now(),'Title','多易教育') ; INSERT INTO stripe_log_table VALUES (now(),'Subject','大數據'),(now(),'WARNING','學大數據到多易教育') ;
StripeLog 引擎將全部列存儲在一個文件中。對每一次 Insert 請求,ClickHouse 將數據塊追加在表文件的末尾,逐列寫入。服務器
ClickHouse 爲每張表寫入如下文件:網絡
data.bin — 數據文件。多線程
index.mrk — 帶標記的文件。標記包含了已插入的每一個數據塊中每列的偏移量。併發
StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操做。ide
讀數據性能
帶標記的文件使得 ClickHouse 能夠並行的讀取數據。這意味着 SELECT 請求返回行的順序是不可預測的。使用 ORDER BY 子句對行進行排序。
咱們使用兩次 INSERT 請求從而在 data.bin 文件中建立兩個數據塊。
ClickHouse 在查詢數據時使用多線程。每一個線程讀取單獨的數據塊並在完成後獨立的返回結果行。這樣的結果是,大多數狀況下,輸出中塊的順序和輸入時相應塊的順序是不一樣的。例如:
select * from stripe_log_table ;
1.2 TinyLog
最簡單的表引擎,用於將數據存儲在磁盤上。每列都存儲在單獨的壓縮文件中,寫入時,數據將附加到文件末尾。
該引擎沒有併發控制,不容許併發操做
- 只支持併發讀
- 若是同時從表中讀取和寫入數據,則讀取操做將拋出異常;
- 若是同時寫入多個查詢中的表,則數據將被破壞。
-- 建表 create table tb_tinylog(id Int8 , name String , age Int8) engine=TinyLog ; -- 插入數據 insert into tb_tinylog values(1,'馬雲',56),(2,'馬化騰',55),(3,'馬克思',123) ; -- 查詢數據 SELECT * FROM tb_tinylog ┌─id─┬─name───┬─age─┐ │ 1 │ 馬雲 │ 56 │ │ 2 │ 馬化騰 │ 55 │ │ 3 │ 馬克思 │ 123 │ └────┴────────┴─────┘
查看磁盤中存儲的數據
數據存儲在機器的磁盤上,每列一個文件,插入數據向列文件的後面追加
再插入一條數據後, 存儲列數據的文件的大小增長了
age.bin 和 id.bin,name.bin 是壓縮過的對應的列的數據,sizes.json 中記錄了每一個 *.bin 文件的大小:
cat sizes.json
{"yandex":{"age%2Ebin":{"size":"56"},"id%2Ebin":{"size":"56"},"name%2Ebin":{"size":"87"}}
這種表引擎的典型用法是 write-once:首先只寫入一次數據,而後根據須要屢次讀取。此引擎適用於相對較小的表(建議最多1,000,000行)。若是有許多小表,則使用此表引擎是適合的,由於它比須要打開的文件更少。當擁有大量小表時,可能會致使性能低下。 不支持索引。
1.3 Log
日誌與 TinyLog 的不一樣之處在於,«標記» 的小文件與列文件存在一塊兒。這些標記寫在每一個數據塊上,而且包含偏移量,這些偏移量指示從哪裏開始讀取文件以便跳過指定的行數。這使得能夠在多個線程中讀取表數據。對於併發數據訪問,能夠同時執行讀取操做,而寫入操做則阻塞讀取和其它寫入。Log 引擎不支持索引。一樣,若是寫入表失敗,則該表將被破壞,而且從該表讀取將返回錯誤。Log 引擎適用於臨時數據,write-once 表以及測試或演示目的。
-- 建表 create table tb_log(id Int8 , name String , age Int8) engine=Log ; --插入數據 insert into tb_log values(1,'馬雲',56),(2,'馬化騰',55),(3,'馬克思',123) ; insert into tb_log values(4,'Hangge',26),(5,'Taoge',35),(6,'Xingge',45) ;
1.4 總結
共同屬性
數據存儲在磁盤上。
寫入時將數據追加在文件末尾。
不支持突變操做。
不支持索引。
這意味着 `SELECT` 在範圍查詢時效率不高。
非原子地寫入數據。
若是某些事情破壞了寫操做,例如服務器的異常關閉,你將會獲得一張包含了損壞數據的表。
差別
Log 和 StripeLog 引擎支持:
併發訪問數據的鎖。
`INSERT` 請求執行過程當中表會被鎖定,而且其餘的讀寫數據的請求都會等待直到鎖定被解除。若是沒有寫數據的請求,任意數量的讀請求均可以併發執行。
並行讀取數據。
在讀取數據時,ClickHouse 使用多線程。 每一個線程處理不一樣的數據塊。
Log 引擎爲表中的每一列使用不一樣的文件。StripeLog 將全部的數據存儲在一個文件中。所以 StripeLog 引擎在操做系統中使用更少的描述符,可是 Log 引擎提供更高的讀性能。
TinyLog 引擎是該系列中最簡單的引擎而且提供了最少的功能和最低的性能。TingLog 引擎不支持並行讀取和併發數據訪問,並將每一列存儲在不一樣的文件中。它比其他兩種支持並行讀取的引擎的讀取速度更慢,而且使用了和 Log 引擎一樣多的描述符。你能夠在簡單的低負載的情景下使用它。
2 MergeTree系列
MergeTree系列的表引擎是ClickHouse數據存儲功能的核心。它們提供了用於彈性和高性能數據檢索的大多數功能:列式存儲,自定義分區,稀疏的主索引,輔助數據跳過索引等。
基本MergeTree表引擎能夠被認爲是單節點ClickHouse實例的默認表引擎,由於它在各類用例中通用且實用。
對於生產用途,ReplicatedMergeTree是必經之路,由於它爲常規MergeTree引擎的全部功能增長了高可用性。一個額外的好處是在數據提取時自動進行重複數據刪除,所以若是在插入過程當中出現網絡問題,該軟件能夠安全地重試。
MergeTree系列的全部其餘引擎爲某些特定用例添加了額外的功能。一般,它是做爲後臺的其餘數據操做實現的。
MergeTree引擎的主要缺點是它們很重。所以,典型的模式是沒有太多。若是您須要許多小表(例如用於臨時數據)
2.1 MergeTree
2.1.1 基本語法
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2], ... INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1, INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2) ENGINE = MergeTree()ORDER BY expr[PARTITION BY expr][PRIMARY KEY expr][SAMPLE BY expr][TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...][SETTINGS name=value, ...]
2.1.2 參數解讀
ENGINE—引擎的名稱和參數。ENGINE = MergeTree()。該MergeTree引擎沒有參數。
ORDER BY —排序鍵
列名稱或任意表達式的元組。範例:ORDER BY (CounterID, EventDate)。
若是PRIMARY KEY子句未明肯定義主鍵,則ClickHouse會將排序鍵用做主鍵。
ORDER BY tuple()若是不須要排序,請使用語法。
PARTITION BY— 分區鍵。可選的。
要按月進行分區,請使用toYYYYMM(date_column)表達式,其中的date_column是日期類型爲Date的列。此處的分區名稱具備"YYYYMM"格式。
PRIMARY KEY—主鍵(與排序鍵)不一樣。可選的。
默認狀況下,主鍵與排序鍵(由ORDER BY子句指定)相同。所以,在大多數狀況下,無需指定單獨的PRIMARY KEY子句。
SAMPLE BY—用於採樣的表達式。可選的。
若是使用採樣表達式,則主鍵必須包含它。範例:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。
TTL—規則列表,用於指定行的存儲持續時間並定義磁盤和卷之間零件自動移動的邏輯。可選的。
結果必須有一個Date或一DateTime列。例:
TTL date + INTERVAL 1 DAY
規則的類型DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'指定了在知足表達式(達到當前時間)時要對零件執行的操做:刪除過時的行,將零件(若是對零件中的全部行都知足表達式)移動到指定的磁盤(TO DISK 'xxx')或到音量(TO VOLUME 'xxx')。規則的默認類型爲刪除(DELETE)。能夠指定多個規則的列表,但最多隻能有一個DELETE規則。
SETTINGS—控制MergeTree(可選)行爲的其餘參數:
- index_granularity—索引標記之間的最大數據行數。默認值:8192。請參見數據存儲。
- index_granularity_bytes—數據粒度的最大大小(以字節爲單位)。默認值:10Mb。要僅按行數限制顆粒大小,請設置爲0(不建議)。請參閱數據存儲。
- enable_mixed_granularity_parts—啓用或禁用過渡以經過index_granularity_bytes設置控制顆粒尺寸。在版本19.11以前,只有index_granularity用於限制顆粒大小的設置。index_granularity_bytes從具備大行(數十和數百MB)的表中選擇數據時,此設置可提升ClickHouse性能。若是您的表具備大行,則能夠爲表啓用此設置以提升SELECT查詢效率。
- use_minimalistic_part_header_in_zookeeper— ZooKeeper中數據部件頭的存儲方法。若是爲use_minimalistic_part_header_in_zookeeper=1,則ZooKeeper存儲的數據較少。有關更多信息,請參閱「服務器配置參數」中的設置說明。
- min_merge_bytes_to_use_direct_io—使用對存儲磁盤的直接I / O訪問所需的最小合併操做數據量。合併數據部分時,ClickHouse會計算要合併的全部數據的總存儲量。若是卷超過min_merge_bytes_to_use_direct_io字節,ClickHouse將使用直接I / O接口(O_DIRECT選項)讀取數據並將數據寫入存儲磁盤。若是爲min_merge_bytes_to_use_direct_io = 0,則直接I / O被禁用。默認值:10 * 1024 * 1024 * 1024字節。
- merge_with_ttl_timeout—重複與TTL合併以前的最小延遲(以秒爲單位)。默認值:86400(1天)。
- write_final_mark—啓用或禁用在數據部分的末尾(最後一個字節以後)寫入最終索引標記。默認值:1.不要關閉它。
- merge_max_bloCK_size—合併操做的塊中的最大行數。默認值:8192
- storage_policy—存儲策略。請參閱使用多個塊設備進行數據存儲。
- min_bytes_for_wide_part,min_rows_for_wide_part—能夠以Wide格式存儲的數據部分中的最小字節/行數。您能夠設置這些設置之一,所有或所有。請參閱數據存儲。
2.1.3 建表示例
建表 create table tb_merge_tree( id Int8 , name String , ctime Date ) engine=MergeTree() order by id partition by name ; 插入數據 insert into tb_merge_tree values (1,'hng','2020-08-07'),(4,'hng','2020-08-07'),(3,'ada','2020-08-07'),(2,'ada','2020-08-07') ;
指定的分區字段是name
指定的排序字段是id
再次插入數據 insert into tb_merge_tree values(5,'ada','2020-08-07'),(6,'hng','2020-08-07') ;
每批次的插入數據做爲一個基礎單元進行分區,區內數據按照指定的字段進行排序
進入到某個分區目錄下
[root@linux04 8cc7880f023bd2c11f539b5088249423_1_1_0]# ll
total 48
-rw-r-----. 1 ClickHouse ClickHouse 361 Aug 5 14:43 cheCKsums.txt
-rw-r-----. 1 ClickHouse ClickHouse 74 Aug 5 14:43 columns.txt 全部的列
-rw-r-----. 1 ClickHouse ClickHouse 1 Aug 5 14:43 count.txt 記錄數據的條數
-rw-r-----. 1 ClickHouse ClickHouse 30 Aug 5 14:43 ctime.bin
-rw-r-----. 1 ClickHouse ClickHouse 48 Aug 5 14:43 ctime.mrk2
-rw-r-----. 1 ClickHouse ClickHouse 28 Aug 5 14:43 id.bin
-rw-r-----. 1 ClickHouse ClickHouse 48 Aug 5 14:43 id.mrk2
-rw-r-----. 1 ClickHouse ClickHouse 8 Aug 5 14:43 minmax_name.idx
-rw-r-----. 1 ClickHouse ClickHouse 34 Aug 5 14:43 name.bin
-rw-r-----. 1 ClickHouse ClickHouse 48 Aug 5 14:43 name.mrk2
-rw-r-----. 1 ClickHouse ClickHouse 4 Aug 5 14:43 partition.dat
-rw-r-----. 1 ClickHouse ClickHouse 2 Aug 5 14:43 primary.idx
- *.bin是按列保存數據的文件
- *.mrk保存塊偏移量
- primary.idx保存主鍵索引
合併屢次插入數據的分區
optimize table tb_merge_tree ;
再合併一次 optimize table tb_merge_tree ;
合併完之後數據在磁盤上的存儲是
過段時間之後CK內部自動的會刪除合併前的多餘的文件夾
在磁盤上的數據組織結構是
2.2
2,3
2,4
2.5