ClickHouse學習筆記


 

1. 概述

ClickHouse是一個用於聯機分析(OLAP:Online Analytical Processing)的列式數據庫管理系統(DBMS:Database Management System),簡稱CK

ClickHouse是一個完全的列式數據庫管理系統,允許在運行時創建表和數據庫,加載數據和運行查詢,而無需重新配置和重新啟動服務器,支持線性擴展,簡單方便,高可靠性,容錯

ClickHouse官方文檔:https://clickhouse.yandex/docs/en/

2. 應用場景

OLAP場景關鍵特征:

  • 大多數是讀請求
  • 數據總是以相當大的批(> 1000 rows)進行寫入
  • 不修改已添加的數據
  • 每次查詢都從數據庫中讀取大量的行,但是同時又僅需要少量的列
  • 寬表,即每個表包含着大量的列
  • 較少的查詢(通常每台服務器每秒數百個查詢或更少)
  • 對於簡單查詢,允許延遲大約50毫秒
  • 列中的數據相對較小: 數字和短字符串(例如,每個UR60個字節)
  • 處理單個查詢時需要高吞吐量(每個服務器每秒高達數十億行)
  • 事務不是必須的
  • 對數據一致性要求低
  • 每一個查詢除了一個大表外都很小
  • 查詢結果明顯小於源數據,換句話說,數據被過濾或聚合后能夠被盛放在單台服務器的內存中

應用場景:

用於結構良好清晰且不可變的事件或日志流分析

不適合的場景:

事務性工作(OLTP),高請求率的鍵值訪問低延遲的修改或刪除已存在數據,Blob或文檔存儲,超標准化數據

3. 數據類型

  • 整型

固定長度的整型,包括有符號整型或無符號整型。

整型范圍:

Int8 - [-128 : 127]

Int16 - [-32768 : 32767]

Int32 - [-2147483648 : 2147483647]

Int64 - [-9223372036854775808 : 9223372036854775807]

無符號整型范圍:

UInt8 - [0 : 255] :可以使用 UInt8 類型,取值限制為01作為Boolean

UInt16 - [0 : 65535]

UInt32 - [0 : 4294967295]

UInt64 - [0 : 18446744073709551615]

  • 浮點型

建議盡可能以整數形式存儲數據。

Float32 - float

Float64 - double

Decimal32(S) - [ -1 * 10^(9 - S) : 1 * 10^(9 - S) ]

Decimal64(S) - [ -1 * 10^(18 - S) : 1 * 10^(18 - S) ]

Decimal128(S) - [ -1 * 10^(38 - S) : 1 * 10^(38 - S) ]

Decimal(P, S)

P - 精度。有效范圍:[1:38],決定可以有多少個十進制數字(包括分數)。

S - 規模。有效范圍:[0P],決定數字的小數部分中包含的小數位數。

  • 字符串型

文本格式建議使用UTF-8 編碼。

String:任意長度

FixedString(N):固定長度N的字符串,N必須是嚴格的正自然數。

UUID:默認值00000000-0000-0000-0000-000000000000

  • 日期型

Date:最小值為0000-00-00

DateTime:最小值為 0000-00-00 00:00:00

  • 枚舉型

Enum8: 'String'= Int8 對描述。

Enum16: 'String'= Int16 對描述。

  • 數組型

Array(T):由T類型元素組成的數組,T可以是任意類型,包含數組類型,但不推薦使用多維數組。

  • 元祖型

Tuple(T1, T2, ...):不能在表中存儲元組(除了內存表),它們可以用於臨時列分組。

  • 其他

Nullable(TypeName):許用特殊標記 (NULL) 表示"缺失值",可以與 TypeName 的正常值存放一起。例如,Nullable(Int8) 類型的列可以存儲 Int8 類型值,而沒有值的行將存儲 NULL

Nested(Name1 Type1, Name2 Type2, ...):嵌套數據結構類似於嵌套表。嵌套數據結構的參數(列名和類型)與 CREATE 查詢類似。每個表可以包含任意多行嵌套數據結構。

IPv4:如116.253.40.133

IPv6:如2a02:aa08:e000:3100::2

4. 表引擎

表引擎(即表的類型)決定了:

  • 數據的存儲方式和位置,寫到哪里以及從哪里讀取數據
  • 支持哪些查詢以及如何支持。
  • 並發數據訪問。
  • 索引的使用(如果存在)。
  • 是否可以執行多線程請求。
  • 數據復制參數。

在讀取時,引擎只需要輸出所請求的列,但在某些情況下,引擎可以在響應請求時部分處理數據。對於大多數正式的任務,應該使用MergeTree族中的引擎。

4.1. MergeTree Family

MergeTree(合並樹)引擎及其家族(*MergeTree)的其他引擎是ClickHouse健壯性最強的表引擎。

主要特點:

  • 存儲的數據按主鍵排序。允許創建一個小的稀疏索引來幫助快速查詢數據
  • 允許在指定分區鍵時使用分區。
  • 支持數據復制
  • 支持數據采樣。

4.1.1. MergeTree

建表語句:

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, ...] 
  • ON CLUSTER cluster:指定分片,可用於建分布式表。
  • ENGINE - 引擎名和參數(必填)
  • PARTITION BY — 分區鍵(可選)

參數為Date類型,默認天分區;要按月分區,可以使用表達式toYYYYMM(date_column)

  • ORDER BY — 表的排序鍵(可選)

可以是一組列的元組或任意的表達式。例如: ORDER BY (CounterID, EventDate)

  • PRIMARY KEY - 主鍵(可選),如果要設成跟排序鍵不相同。

通常主鍵默認和排序(ORDER BY)字段相同,不需另外指定。

  • SAMPLE BY — 用於抽樣的表達式(可選)

如果要用抽樣表達式,主鍵中必須包含這個表達式。例如: SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))

  • SETTINGS — 影響 MergeTree 性能的額外參數(可選)

控制合並樹的其他參數設置(可選)。index_granularity——索引的粒度。索引標記之間的數據行數。默認值:8192

新版CLickHouse不建議使用以下方式建表:

ENGINE [=] MergeTree(date-column [, sampling_expression], (primary, key), index_granularity)  

4.1.2. ReplacingMergeTree

該引擎和MergeTree的不同之處在於它會刪除具有相同主鍵的重復項。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = ReplacingMergeTree([ver])  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...]  
  • ver — 版本列。類型為 UInt*, Date  DateTime。可選參數。

合並的時候,ReplacingMergeTree 從所有具有相同主鍵的行中選擇一行留下:如果 ver 列未指定,選擇最后一條。如果 ver 列已指定,選擇 ver 值最大的版本。

4.1.3. SummingMergeTree

該引擎繼承自 MergeTree。區別在於,當合並SummingMergeTree表的數據片段時,ClickHouse 會把所有具有相同主鍵的行合並為一行,該行包含了被合並的行中具有數值數據類型的列的匯總值。如果主鍵的組合方式使得單個鍵值對應於大量的行,則可以顯著的減少存儲空間並加快數據查詢的速度。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = SummingMergeTree([columns])  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...]  
  • columns - 包含了將要被匯總的列的列名的元組。可選參數。 所選的列必須是數值類型,並且不可位於主鍵中。

如果沒有指定 columnsClickHouse 會把所有不在主鍵中的數值類型的列都進行匯總。

4.1.4. AggregatingMergeTree

該引擎繼承自 MergeTree,並改變了數據片段的合並邏輯。 ClickHouse 會將相同主鍵的所有行(在一個數據片段內)替換為單個存儲一系列聚合函數狀態的行。

可以使用 AggregatingMergeTree 表來做增量數據統計聚合,包括物化視圖的數據聚合。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = AggregatingMergeTree()  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...]  

4.1.5. CollapsingMergeTree

該引擎繼承於 MergeTree,並在數據塊合並算法中添加了折疊行的邏輯。

CollapsingMergeTree 會異步的刪除(折疊)這些除了特定列 Sign  1  -1 的值以外,其余所有字段的值都相等的成對的行。沒有成對的行會被保留。

該引擎可以顯著的降低存儲量並提高 SELECT 查詢效率。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = CollapsingMergeTree(sign)  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...] 
  • sign—類型列的名稱:1狀態行,-1取消行。

列數據類型 — Int8

4.1.6. VersionedCollapsingMergeTree

引擎繼承了MergeTree,並將折疊行的邏輯添加到合並數據部分的算法中。版本化的collapsingmergetreecollapsingmergetree具有相同的用途,但使用了不同的折疊算法,允許在多個線程中以任意順序插入數據。尤其是,版本列有助於正確折疊行,即使它們是按錯誤的順序插入的。相反,collapsingmergetree只允許嚴格連續插入。

允許快速寫入不斷變化的對象狀態。

刪除背景中的舊對象狀態。這大大減少了存儲容量。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = VersionedCollapsingMergeTree(sign, version)  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...]  
  • sign—類型的列的名稱:1狀態行,-1取消行。

列數據類型應為Int8

  • version—具有對象狀態版本的列的名稱。

列數據類型應為Uint*

4.1.7. GraphiteMergeTree

該引擎繼承於 MergeTree用於細化和聚合/平均(匯總)Graphite Data

如果不需要匯總,您可以使用任何Clickhouse表引擎來存儲Graphite Data,但是如果需要匯總,請使用GraphiteMergeTree。該引擎減少了存儲容量,並提高了Graphite Data的效率。

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
Path String,  
Time DateTime,  
Value <Numeric_type>,  
Version <Numeric_type>  
...  
) ENGINE = GraphiteMergeTree(config_section)  
[PARTITION BY expr]  
[ORDER BY expr]  
[SAMPLE BY expr]  
[SETTINGS name=value, ...]  
  • config_section—配置文件中配置項的名稱,

4.1.8. 數據副本

只有 MergeTree 系列里的表可支持副本:

  • ReplicatedMergeTree
  • ReplicatedSummingMergeTree
  • ReplicatedReplacingMergeTree
  • ReplicatedAggregatingMergeTree
  • ReplicatedCollapsingMergeTree
  • ReplicatedVersionedCollapsingMergeTree
  • ReplicatedGraphiteMergeTree

副本是表級別的,不是整個服務器級的。所以,服務器里可以同時有復制表和非復制表。

副本不依賴分片。每個分片有它自己的獨立副本。

4.2. Log Family

這些引擎是為了需要寫入許多小數據量(少於一百萬行)的表的場景而開發的。

這系列的引擎有:

主要特點:

  • 數據存儲在磁盤上。
  • 寫入時將數據追加在文件末尾。
  • 不支持突變操作。
  • 不支持索引。意味着 SELECT 在范圍查詢時效率不高。
  • 非原子地寫入數據。

如果某些事情破壞了寫操作,例如服務器的異常關閉,你將會得到一張包含了損壞數據的表。

4.2.1. 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  

4.2.2. TinyLog

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

並發數據訪問不受任何限制:如果同時從表中讀取並在不同的查詢中寫入,則讀取操作將拋出異常,如果同時寫入多個查詢中的表,則數據將被破壞。

這種表引擎的典型用法是 write-once:首先只寫入一次數據,然后根據需要多次讀取。查詢在單個流中執行。換句話說,此引擎適用於相對較小的表(建議最多1,000,000行)。如果您有許多小表,則使用此表引擎是適合的,因為它比Log引擎更簡單(需要打開的文件更少)。當您擁有大量小表時,可能會導致性能低下,但在可能已經在其它 DBMS 時使用過,則您可能會發現切換使用 TinyLog 類型的表更容易。不支持索引。

4.2.3. Log

LogTinyLog的不同之處在於,"標記" 的小文件與列文件存在一起。這些標記寫在每個數據塊上,並且包含偏移量,這些偏移量指示從哪里開始讀取文件以便跳過指定的行數。這使得可以在多個線程中讀取表數據。對於並發數據訪問,可以同時執行讀取操作,而寫入操作則阻塞讀取和其它寫入。Log 引擎不支持索引。同樣,如果寫入表失敗,則該表將被破壞,並且從該表讀取將返回錯誤。Log 引擎適用於臨時數據,write-once 表以及測試或演示目的。

4.3. Distributed

分布式引擎本身不存儲數據, 但可以在多個服務器上進行分布式查詢。讀是自動並行的。讀取時,遠程服務器表的索引(如果有的話)會被使用。分布式引擎參數:服務器配置文件中的集群名,遠程數據庫名,遠程表名,數據分片鍵(可選)。 

示例:

Distributed(logs, default, hits[, sharding_key])  

將會從位於logs”集群中 default.hits 表所有服務器上讀取數據。 遠程服務器不僅用於讀取數據,還會對盡可能數據做部分處理。 例如,對於使用 GROUP BY 的查詢,數據首先在遠程服務器聚合,之后返回聚合函數的中間狀態給查詢請求的服務器。再在請求的服務器上進一步匯總數據。

4.4. Memory

Memory 引擎以未壓縮的形式將數據存儲在RAM中。數據完全以讀取時獲得的形式存儲。換句話說,從這張表中讀取是很輕松的。並發數據訪問是同步的。鎖范圍小:讀寫操作不會相互阻塞。不支持索引。閱讀是並行化的。在簡單查詢上達到最大生產率(超過10 GB /秒),因為沒有磁盤讀取,不需要解壓縮或反序列化數據。(值得注意的是,在許多情況下,與 MergeTree 引擎的性能幾乎一樣高)。重新啟動服務器時,表中的數據消失,表將變為空。通常,使用此表引擎是不合理的。但是,它可用於測試,以及在相對較少的行(最多約100,000,000)上需要最高性能的查詢。

5. SQL語法

  • SELECT查詢
SELECT [DISTINCT] expr_list  
[FROM [db.]table | (subquery) | table_function] [FINAL]  
[SAMPLE sample_coeff]  
[ARRAY JOIN ...]  
[GLOBAL] ANY|ALINNER|LEFT JOIN (subquery)|table USING columns_list  
[PREWHERE expr]  
[WHERE expr]  
[GROUP BY expr_list] [WITH TOTALS]  
[HAVING expr]  
[ORDER BY expr_list]  
[LIMIT [n, ]m]  
[UNION ALL ...]  
[INTO OUTFILE filename]  
[FORMAT format]  
[LIMIT n BY columns]  

語法與關系型數據庫MYSQL基本一致。

除了SELECT之后的表達式列表(expr_list),所有的子句都是可選的。

  • INSERT寫入
INSERT INTO [db.]table [(c1, c2, c3)] VALUES (v11, v12, v13), (v21, v22, v23), ...  

語法與關系型數據庫MYSQL基本一致。

  • remote數據同步
INSERT INTO [db.][tablename] SELECT * FROM remote(ip,db.tablename[,username[,password])  
  • mysql表同步
CREATE TABLE tmp ENGINE = MergeTree ORDER BY id AS SELECT * FROM mysql('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_duplicate_clause']);  
  • CREATE創建
CREATE DATABASE [IF NOT EXISTS] db_name;  
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]  
(  
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],  
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],  
...  
) ENGINE = engine  
  • ALTER修改
ALTER TABLE [db].name [ON CLUSTER cluster] ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN ...  
  • DROP 刪庫/
DROP DATABASE [IF EXISTS] db [ON CLUSTER cluster]   #刪除數據庫
DROP [TEMPORARY] TABLE [IF EXISTS] [db.]name [ON CLUSTER cluster]  #刪除表
  • ALTER修改
ALTER TABLE [db.]table DELETE WHERE filter_expr...   #刪除數據
ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] WHERE ...  #修改數據
  • TRUNCATE 清表
TRUNCATE TABLE [IF EXISTS] [db.]name [ON CLUSTER cluster]  

6. 實踐

ClickHousegalaxy-0-10galaxy-0-14五台物理機上有安裝部署,本次實踐是基於此測試集群進行操作。

  • 分片配置文件路徑:/etc/metrika.xml

里面有配置分片名稱(cluster_3shards_1replicas)及信息,若要創建分布式庫/表,則在語句末尾加上ON CLUSTER cluster_3shards_1replicas即可。

登陸ClickHouse通過SQL也可查看分片信息:

 

  • 配置文件路徑:/etc/clickhouse-server/config.xml
  • 日志文件路徑:/var/log/clickhouse-server/
  • 建表信息路徑:/data/clickhouse/metadata/
  • 分區數據路徑:/data/clickhouse/data/

下面以進行分布式操作為例(單機操作省略[ON CLUSTER cluster_3shards_1replicas]即可):

6.1. 連接ClickHouse

clickhouse-client -m -u [username] -h [ip] --password [password] --port [port]  
  • username:用戶名
  • password:密碼
  • ip:服務器IP
  • port:端口
  • -m:允許多行查詢

6.2. 創建數據庫

創建分布式測試數據庫test

CREATE DATABASE test ON CLUSTER cluster_3shards_1replicas;  

6.3. 創建表

以深圳通原始數據為例,在每個分片上創建表szt_data

CREATE TABLE test.szt_data ON CLUSTER cluster_3shards_1replicas  
(  
id String,   
card_id String,   
deal_time String,   
trade_type String,   
trade_sum Int16,   
trade_value Int16,   
terminal_code String,   
com_line String,   
line_station String,   
car_gate String,   
flag String,   
finish_time Date  
)  
ENGINE = MergeTree()  
PARTITION BY finish_time  
ORDER BY (card_id, terminal_code)  
SETTINGS index_granularity = 8192  

以結算日期(Datefinish_time)按天進行分區,以卡號和設備編號進行排序,使用默認索引粒度8192

  • toYYYYMM(EventDate):按月分區
  • toMonday(EventDate):按周分區
  • toDate(EventDate):按天分區
  • PARTITION BY cloumn_name:指定列分區(不建議以非日期類型作為分區)

對於分區可進行如下操作:

ALTER TABLE [db.][tablename] DROP PARTITION [partition]  #刪除分區  
ALTER TABLE [db.][tablename] DETACH PARTITION [partition]#下線分區  
ALTER TABLE [db.][tablename] ATTACH PARTITION [partition]#恢復分區  
ALTER TABLE [db.][tablename] FREEZE PARTITION [partition]#備份分區  

創建分布式表all_szt_data

CREATE TABLE test.all_szt_data 
ON CLUSTER cluster_3shards_1replicas AS test.szt_data 
ENGINE = Distributed(cluster_3shards_1replicas, test, szt_data, rand())  
  • cluster_3shards_1replicas:配置文件中集群名稱
  • test:數據庫名稱
  • szt_data:表名
  • rand():分片方式,隨機

6.4. 刪除庫/

語法同mysql,若要刪除創建的分布式庫/表,在末尾加上ON CLUSTER cluster_3shards_1replicas即可。

DROP DATABASE test;   #刪除數據庫
DROP TABLE szt_data;   #刪除表
DROP TABLE all_szt_data;   #刪除分布式表

6.5. 數據導入

上面建表時分別在各機器上創建了本地表(szt_data)和分布式表(all_szt_data),數據導入時可指定導入哪台機器上或者導入分布式表,若導入分布式表數據會隨機分到各分片上。

  • 命令行導入
clickhouse-client -u [username] -h [ip] --password [password] --port [port] --query="INSERT INTO [tablename] FORMAT CSV" < [filepath]  
cat [filepath] | clickhouse-client -u [username] -h [ip] --password [password] --port [port] --query="INSERT INTO [tablename] FORMAT CSV"   

同時可在clickhouse-client命令后面添加以下選項:

  • --format_csv_delimiter:指定分隔符。上面命令中文件是以逗號分割
  • --input_format_allow_errors_num:容錯數量

其他選項可輸入命令clickhouse-client --help查看。

6.6. 數據修改

語法與普通關系型數據庫稍微有些區別,由於分布式表並不存儲數據,所以無法直接對分布式表進行修改,對於本地表中數據指定記錄的修改,可用以下方式:

ALTER TABLE test.szt_data UPDATE trade_sum=1000 WHERE id='20181016094339_020001045';  #修改數據
ALTER TABLE test.szt_data DELETE WHERE id='20181016094339_020001045';  #刪除數據

6.7. 查詢

語法同普通關系型數據庫

SELECT * FROM test.szt_data LIMIT 10;   #查詢本地表
SELECT * FROM test.all_szt_data LIMIT 10;   #查詢分布式表
  • 查看分片信息  
SELECT * FROM system.clusters;  
  • 查看分區信息
SELECT partition, name, active FROM system.parts WHERE table = 'szt_data';  

對應存儲目錄下的文件:

 

從目錄結構可看出,ClickHouse為列式存儲,每個數據文件夾下均存儲了以列為單位的文件。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM