數倉選型必列入考慮的OLAP列式資料庫ClickHouse(上)
概述
定義
ClickHouse官網地址 //clickhouse.com/ 最新版本22.4.5.9
ClickHouse是俄羅斯的 Yandex 於 2016 年開源的用於在線分析處理查詢(OLAP :Online Analytical Processing)MPP架構的列式存儲資料庫(DBMS:Database Management System),能夠使用 SQL 查詢實時生成分析數據報告。ClickHouse的全稱是Click Stream,Data WareHouse。ClickHouse可以做用戶行為分析,流批一體,其線性擴展和可靠性保障能夠原生支援 分片和副本,shard + replication,ClickHouse沒有走hadoop生態自己實現分散式存儲。
- OLAP場景的關鍵特徵
- 絕大多數是讀請求
- 數據以相當大的批次(> 1000行)更新,而不是單行更新;或者根本沒有更新。
- 已添加到資料庫的數據不能修改。
- 對於讀取,從資料庫中提取相當多的行,但只提取列的一小部分。
- 寬表,即每個表包含著大量的列
- 查詢相對較少(通常每台伺服器每秒查詢數百次或更少)
- 對於簡單查詢,允許延遲大約50毫秒
- 列中的數據相對較小:數字和短字元串(例如,每個URL 60個位元組)
- 處理單個查詢時需要高吞吐量(每台伺服器每秒可達數十億行)
- 事務不是必須的
- 對數據一致性要求低
- 每個查詢有一個大表。除了他以外,其他的都很小。
- 查詢結果明顯小於源數據。換句話說,數據經過過濾或聚合,因此結果適合於單個伺服器的RAM中
- 很容易可以看出,OLAP場景與其他通常業務場景(例如,OLTP或K/V)有很大的不同, 因此想要使用OLTP或Key-Value資料庫去高效的處理分析查詢場景,並不是非常完美的適用方案。例如,使用OLAP資料庫去處理分析請求通常要優於使用MongoDB或Redis去處理分析請求。
- 列式資料庫更適合OLAP場景的原因
- 針對分析類查詢,通常只需要讀取表的一小部分列。在列式資料庫中你可以只讀取你需要的數據。例如,如果只需要讀取100列中的5列,這將幫助你最少減少20倍的I/O消耗。
- 由於數據總是打包成批量讀取的,所以壓縮是非常容易的。同時數據按列分別存儲這也更容易壓縮。這進一步降低了I/O的體積。
- 由於I/O的降低,這將幫助更多的數據被系統快取。
- CPU
- 向量引擎:所有的操作都是為向量而不是為單個值編寫的。這意味著多個操作之間的不再需要頻繁的調用,並且調用的成本基本可以忽略不計。操作程式碼包含一個優化的內部循環。
- 程式碼生成:生成一段程式碼,包含查詢中的所有操作。
特性
- 真正的列式資料庫管理系統:ClickHouse不單單是一個資料庫, 它是一個資料庫管理系統。因為它允許在運行時創建表和資料庫、載入數據和運行查詢,而無需重新配置或重啟服務.
- 數據壓縮:支援通用壓縮編解碼器之外,ClickHouse還提供針對特定類型數據的專用編解碼器。
- 數據的磁碟存儲:ClickHouse被設計用於工作在傳統磁碟上的系統,它提供每GB更低的存儲成本,但如果可以使用SSD和記憶體,它也會合理的利用這些資源。
- 多核心並行處理
- 多伺服器分散式處理
- 支援SQL
- 向量引擎
- 實時的數據更新
- 索引
- 適合在線查詢
- 支援近似計算
- 自適應連接演算法
- 支援數據複製和數據完整性
- 角色的訪問控制
- 限制
- 沒有完整的事務支援。
- 缺少高頻率,低延遲的修改或刪除已存在數據的能力。僅能用於批量刪除或修改數據,但這符合 GDPR。
- 稀疏索引使得ClickHouse不適合通過其鍵檢索單行的點查詢。
性能
- 單個大查詢吞吐量:如果數據被放置在page cache中,則一個不太複雜的查詢在單個伺服器上大約能夠以2-10GB/s(未壓縮)的速度進行處理。
- 處理短查詢的延遲時間:如果一個查詢使用主鍵並且沒有太多行(幾十萬)進行處理,並且沒有查詢太多的列,那麼在數據被page cache快取的情況下,它的延遲應該小於50毫秒。
- 處理大量短查詢的吞吐量:在相同的情況下,ClickHouse可以在單個伺服器上每秒處理數百個查詢。
- 寫入速度大約為50到200MB/s。如果您寫入的數據每行為1Kb,那麼寫入的速度為50,000到200,000行每秒。
為什麼ClickHouse這麼快?
- 面向列的存儲:源數據通常包含數百甚至數千列,而報表可以只使用其中的少數列。系統需要避免讀取不必要的列,否則最昂貴的磁碟讀取操作將被浪費。
- 索引:ClickHouse將數據結構保存在記憶體中,不僅允許讀取已使用的列,還允許讀取這些列的必要行範圍。
- 數據壓縮:將同一列的不同值存儲在一起通常會帶來更好的壓縮比(與面向行的系統相比),因為在實際數據中,列的相鄰行通常具有相同或不那麼多的不同值。除了通用壓縮,ClickHouse還支援專門的編解碼器,可以使數據更加緊湊。
- 向量化查詢執行:ClickHouse不僅在列中存儲數據,還在列中處理數據。它可以提高CPU快取利用率,並允許使用SIMD CPU指令。
- 可伸縮性:ClickHouse可以利用所有可用的CPU核和磁碟執行單個查詢。不僅在單個伺服器上,而且在集群的所有CPU核和磁碟上也是如此。
安裝部署
系統要求
ClickHouse可以在任何具有x86_64,AArch64或PowerPC64LE CPU架構的Linux,FreeBSD或Mac OS X上運行。
官方預構建的二進位文件通常針對x86_64進行編譯,並利用SSE 4.2
指令集,因此,除非另有說明,支援它的CPU使用將成為額外的系統需求。下面是檢查當前CPU是否支援SSE 4.2的命令:
$ grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"
要在不支援SSE 4.2
或AArch64
,PowerPC64LE
架構的處理器上運行ClickHouse,您應該通過適當的配置調整從源程式碼構建ClickHouse。
可用安裝包
- DEB安裝包
- RPM安裝包
- Tgz安裝包
- Docker安裝包
- 其他環境安裝包
- 使用源碼安裝
安裝包列表:
clickhouse-common-static
— ClickHouse編譯的二進位文件。clickhouse-server
— 創建clickhouse-server
軟連接,並安裝默認配置服務clickhouse-client
— 創建clickhouse-client
客戶端工具軟連接,並安裝客戶端配置文件。clickhouse-common-static-dbg
— 帶有調試資訊的ClickHouse二進位文件。
單機RPM包安裝
單機部署比較簡單,執行完下面四條命令就可以通過clickhouse-client來操作了
yum install -y yum-utils
yum-config-manager --add-repo //packages.clickhouse.com/rpm/clickhouse.repo
yum install -y clickhouse-server clickhouse-client
/etc/init.d/clickhouse-server start
集群部署
ClickHouse集群是一個同質集群,操作步驟如下
- 分別在ckserver1(192.168.5.52)、ckserver2(192.168.5.53)、huawei27(192.168.12.27)這三台上按照上面的單機部署前面3行命令安裝ClickHouse服務端。需提前準備Zookeeper,這樣使用的是提前建好的3台Zookeeper集群(Zookeeper部署可以查看之前的文章)。
- 在配置文件中設置集群配置。主要配置zookeeper、remote_servers和macros節點數據,而macros數據在每個節點分別配置,ckserver1配置為01,ckserver2配置02,huawei27配置為03,在下面示例為配置一個3個分片和3個副本的集群。
<zookeeper>
<node>
<host>huawei27</host>
<port>2181</port>
</node>
<node>
<host>huawei28</host>
<port>2181</port>
</node>
<node>
<host>huawei29</host>
<port>2181</port>
</node>
</zookeeper>
<remote_servers>
<perftest_3shards_3replicas>
<shard>
<replica>
<host>ckserver1</host>
<port>9000</port>
</replica>
<replica>
<host>ckserver2</host>
<port>9000</port>
</replica>
<replica>
<host>huawei27</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>ckserver1</host>
<port>9000</port>
</replica>
<replica>
<host>ckserver2</host>
<port>9000</port>
</replica>
<replica>
<host>huawei27</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>ckserver1</host>
<port>9000</port>
</replica>
<replica>
<host>ckserver2</host>
<port>9000</port>
</replica>
<replica>
<host>huawei27</host>
<port>9000</port>
</replica>
</shard>
</perftest_3shards_3replicas>
</remote_servers>
<macros>
<shard>01</shard>
<replica>01</replica>
</macros>
修改完配置後分別在三台上執行/etc/init.d/clickhouse-server start,查詢集群資訊如下
介面
- ClickHouse提供了一個原生命令行客戶端
clickhouse-client
客戶端支援命令行--host, -h
-– 服務端的host名稱, 默認是localhost
。您可以選擇使用host名稱或者IPv4或IPv6地址。--port
– 連接的埠,默認值:9000。注意HTTP介面以及TCP原生介面使用的是不同埠。--user, -u
– 用戶名。 默認值:default
。--password
– 密碼。 默認值:空字元串。--query, -q
– 使用非交互模式查詢。--database, -d
– 默認當前操作的資料庫. 默認值:服務端默認的配置(默認是default
)。--multiline, -m
– 如果指定,允許多行語句查詢(Enter僅代表換行,不代表查詢語句完結)。--multiquery, -n
– 如果指定, 允許處理用;
號分隔的多個查詢,只在非交互模式下生效。--format, -f
– 使用指定的默認格式輸出結果。--vertical, -E
– 如果指定,默認情況下使用垂直格式輸出結果。這與–format=Vertical
相同。在這種格式中,每個值都在單獨的行上列印,這種方式對顯示寬表很有幫助。--time, -t
– 如果指定,非交互模式下會列印查詢執行的時間到stderr
中。--stacktrace
– 如果指定,如果出現異常,會列印堆棧跟蹤資訊。--config-file
– 配置文件的名稱。--secure
– 如果指定,將通過安全連接連接到伺服器。--history_file
— 存放命令歷史的文件的路徑。--param_<name>
— 查詢參數配置。
- HTTP客戶端:HTTP介面允許您在任何程式語言的任何平台上使用ClickHouse,HTTP介面比原生介面受到更多的限制,但它具有更好的兼容性。默認情況下,
clickhouse-server
會在8123
埠上監控HTTP請求(這可以在配置中修改)。如果你發送了一個未攜帶任何參數的GET /
請求,它會返回一個字元串 «Ok.» - MySQL介面:ClickHouse支援MySQL wire通訊協議。
- JDBC驅動
- 官網驅動
- 第三方驅動:
- ClickHouse-Native-JDBC
- clickhouse4j
- ODBC驅動
- C++客戶端庫
- 第三方工具
- 客戶端開發庫,支援多種語言如Python、Java、Go、Php、NodeJs、Swift、Ruby、R、Scala、C#、Kotlin等等
- 第三方集成庫
- 關係資料庫:MySQL、MSSQL、PostgreSQL
- 消息隊列:Kafka
- 流處理:Flink
- 對象存儲:S3
- 容器編排:Kubernetes
- 監控:Grafana、Prometheus、Zabbix
- 第三方代理
- chproxy
- KittenHouse
- ClickHouse-Bulk
- 第三方開發的可視化介面
- 開源
- Tabix
- HouseOps
- 燈塔
- DBeaver
- clickhouse-cli
- clickhouse-flamegraph
- DBM
- 商業
- Holistics
- DataGrip
- 開源
創建資料庫
默認情況下,ClickHouse使用Atomic資料庫引擎。它提供了可配置的table engines和SQL dialect。創建一個測試資料庫
CREATE DATABASE test ENGINE = Atomic;
use test;
創建數據表
# -m支援多行輸入
clickhouse-client -m
使用最常見的MergeTree表引擎創建一張用戶資訊表user_info
CREATE TABLE user_info
(
id INT,
name String,
age Int8,
sex Int8,
career INT,
birthday Date
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(birthday)
ORDER BY (career, birthday);
# user_info插入兩行數據
insert into user_info values(100,'張三',27,1,1000,'1998-05-21'),(101,'李婷',28,2,1001,'2000-07-25');
# 查詢user_info數據
select * from user_info;
至此,ClickHouse的環境已經完全準備就緒,下一篇我們先通過一個案例需求學習ClickHouse使用,然後再層層深入。