clickhouse入門到實戰及面試(三)


第一章、 clickhouse入門

一、ClickHouse介紹

ClickHouse(開源)是一個面向列的數據庫管理系統(DBMS),用於在線分析處理查詢(OLAP)。

關鍵詞:開源、面向列、聯機分析處理(OLAP)

ClickHouse不僅查詢速度快(相較於hive等類似的分析型DBMS),而且硬件使用效率、容錯性、可靠性、易用性、線性擴展性等高。

1.1 ClickHouse的獨特功能
  • 真正的列式DBMS 除了數據本身外不應該存在其他額外的數據。這意味着為了避免在值旁邊存儲它們的長度“number”,你必須支持固定長度數值類型。

  • 數據壓縮 數據壓縮存儲在性能方面發揮着關鍵作用

  • 數據的磁盤存儲 工作在傳統磁盤上的系統

  • 多核心並行處理 大型查詢以一種自然的方式並行化,占用當前服務器上可用的所有必要資源

  • 多服務器分布式處理 在ClickHouse中,數據可以保存在不同的shard上,每一個shard都由一組用於容錯的replica組成,查詢可以並行的在所有shard上進行處理

  • 支持SQL ClickHouse支持基於SQL的查詢語言,該語言大部分情況下是與SQL標准兼容的。 支持的查詢包括 GROUP BY,ORDER BY,IN,JOIN以及非相關子查詢。 不支持窗口函數和相關子查詢

  • 向量引擎 為了高效的使用CPU,數據不僅僅按列存儲,同時還按向量(列的一部分)進行處理

  • 實時的數據更新 ClickHouse支持在表中定義主鍵。為了使查詢能夠快速在主鍵中進行范圍查找,數據總是以增量的方式有序的存儲在MergeTree中。因此,數據可以持續不斷高效的寫入到表中,並且寫入的過程中不會存在任何加鎖的行為

  • 索引 按照主鍵對數據進行排序,使能夠以幾十毫秒的低延遲對數據進行特定值查找或范圍查找

  • 適合在線查詢 在線查詢意味着在沒有對數據做任何預處理的情況下以極低的延遲處理查詢並將結果加載到用戶的頁面中

  • 支持近似計算 ClickHouse提供各種各樣在允許犧牲數據精度的情況下對查詢進行加速的方法: 1、用於近似計算的各類聚合函數,如:distinct values, medians, quantiles 2、 基於數據的部分樣本進行近似查詢。這時,僅會從磁盤檢索少部分比例的數據。 3、 不使用全部的聚合條件,通過隨機選擇有限個數據聚合條件進行聚合。這在數據聚合條件滿足某些分布條件下,在提供相當准確的聚合結果的同時降低了計算資源的使用。

1.2 OLAP場景特征(適用場景)
  • 絕大多數都是讀請求

  • 數據以相當大的批量寫入(> 1000行),而不是單行。

  • 不再修改已添加的數據

  • 每次查詢都從數據庫中讀取大量的行,但是同時又僅需要少量的列

  • 寬表,即每個表包含着大量的列

  • 較少的查詢(通常每台服務器每秒數百個查詢或更少)

  • 對於簡單查詢,允許延遲大約50毫秒

  • 列中的數據相對較小: 數字和短字符串(例如,每個URL 60個字節)

  • 處理單個查詢時需要高吞吐量(每個服務器每秒高達數十億行)

  • 事務不是必須的

  • 對數據一致性要求低

  • 每一個查詢除了一個大表外,其他都是小表

  • 查詢結果明顯小於源數據。換句話說,數據被過濾或聚合后能夠被存放在單台服務器的內存中

1.3 缺點(不適用場景)
  • 沒有完整的事物支持

  • 缺少高頻率,低延遲的修改或刪除已存在數據的能力。僅能用於批量刪除或修改數據,但這符合 GDPR

  • 稀疏索引使得ClickHouse不適合通過其鍵檢索單行的點查詢

1.4 官方性能對比

ClickHouse的性能超過了市場上現有的類似的面向列的DBMS。它每秒處理數億到10億行,每台服務器每秒處理數百億字節的數據。單個查詢(解壓縮后,僅使用列)的處理性能峰值為每秒2 tb以上。 我們來看看官網提供的對比數據:分析型DBMS的性能比較

img

img

由上圖看出,ClickHouse比傳統的分析型數據庫快100-1000倍。

畢竟是官方自己提供的數據,為了更加真實的性能測試,后面會在實際環境中和GreenPlum等做測試對比。

1.5 數據類型支持

二、安裝部署(Centos7)

2.1 環境准備

參考hadoop集群搭建中的一、安裝環境准備二、安裝zookeeper

2.2 安裝CLickHouse(每台集群)

在此只介紹腳本安裝方式,手動及其他可參考: https://github.com/Altinity/clickhouse-rpm-install/blob/master/README.md https://clickhouse.yandex/docs/zh/getting_started/

Step1: 如果從官方倉庫安裝,需要確保您使用的是x86_64處理器構架的Linux並且支持SSE 4.2指令集 檢查是否支持SSE 4.2:

 

grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"

返回結果應為:“SSE 4.2 supported” Step2: 基於腳本安裝

  1. 安裝依賴

 

sudo yum install -y curl
  1. 下載運行腳本 centos7顯式指定os=centos dist=7兩個參數

 

curl -s https://packagecloud.io/install/repositories/altinity/clickhouse/script.rpm.sh | sudo os=centos dist=7 bash
  1. 查看clickhouse可用安裝包

 

sudo yum list 'clickhouse*'

結果如下列表:有多個可用的包(包括新版本和舊工具),其中一些已經被棄用,因此不需要安裝所有可用的rpm。

img

Step3: 安裝ClickHouse的主要部分——服務器和客戶端應用程序

 

sudo yum install -y clickhouse-server clickhouse-client

查看校驗已安裝列表

 

sudo yum list installed 'clickhouse*'

img

Step4: 配置目錄查看及修改

  • 安裝完后默認的配置文件路徑在/etc/clickhouse-server/下:config.xml(默認系統配置) 、users.xml(用戶相關配置) 通過查看配置文件config.xml,定了默認的數據目錄、臨時目錄、日志目錄等; /var/lib/clickhouse /var/lib/clickhouse/tmp/ /var/log/clickhouse-server 實際生產環境中,這些數據目錄通常放在數據盤而不是系統盤,所以會做相應調整。

  • 默認啟動腳本:/etc/rc.d/init.d/clickhouse-server

  • 最大打開文件數:/etc/security/limits.d/clickhouse.conf clickhouse soft nofile 262144 clickhouse hard nofile 262144

  • 定時任務文件: /etc/cron.d/clickhouse-server(看看就好了。cron進程執行時,就會自動掃描該目錄下的所有文件,按照文件中的時間設定執行后面的命令),文件內容如下:

*/10 * * * * root (which service > /dev/null 2>&1 && (service clickhouse-server condstart ||:)) || /etc/init.d/clickhouse-server condstart > /dev/null 2>&1

  • 安裝二進制文件目錄:/usr/bin/clickhouse*,共享文件目錄:/usr/share/clickhouse/

img

 

大都軟鏈接到了clickhouse這個二進制文件

img

更多服務端配置(/etc/clickhouse-server/config.xml )及說明文檔

Step5: 確保ClickHouse服務器正在運行

 

sudo /etc/init.d/clickhouse-server restart

Step6: 客戶端連接命令

 

clickhouse-client

至此單機安裝完畢。

2.3 集群配置

這一部分官方文檔整理的不夠清晰條理,個人覺得。 首先查看配置文件的文檔,里面大致介紹了服務端配置的覆蓋(替代)文件和用戶配置文件的創建和配置。然后找到分布式文檔參考配置新的內容。具體整理如下步驟。

2.3.1 創建擴展配置文件(metrika.xml)
  • 配置對應config.xml的中的標簽進行復制擴展,新的標簽名應和config.xml中 incl="替換的標簽名"一致。

  • 每個clickhouse-server實例默認配置下對應只能被配置為某個數據分片(shard)的唯一副本(replica)。或添加內部復制端口配置。

默認本節點實例1: <http_port>8123</http_port> <tcp_port>9000</tcp_port> <interserver_http_port>9009</interserver_http_port> 添加本節點實例2 : <http_port>8124</http_port> <tcp_port>9001</tcp_port> <interserver_http_port>9010</interserver_http_port> 參考:https://www.cnblogs.com/freeweb/p/9352947.html

  • 添加zookeeper配置需要重啟集群服務,此時會在zk客戶端查看生產/clickhouse目錄

  • 配置需添加在``中。

完整配置示例如下:

 

<yandex>
<!-- 集群配置 -->
<clickhouse_remote_servers>
   <!-- 集群名稱 -->
   <hdc_3s1r_cluster>
       <!-- 數據分片1 -->
       <shard>
           <weight>1</weight>
           <internal_replication>true</internal_replication>
           <replica>
               <host>hdc-data4</host>
               <port>9000</port>
               <user>default</user>
               <password>Hdc2019</password>
           </replica>
       </shard>

       <!-- 數據分片2 -->
       <shard>
           <weight>1</weight>
           <internal_replication>true</internal_replication>
           <replica>
               <host>hdc-data5</host>
               <port>9000</port>
               <user>default</user>
               <password>Hdc2019</password>
           </replica>
       </shard>

       <!-- 數據分片3 -->
       <shard>
           <weight>1</weight>
           <internal_replication>true</internal_replication>
           <replica>
               <host>hdc-data6</host>
               <port>9000</port>
               <user>default</user>
               <password>Hdc2019</password>
           </replica>
       </shard>
   </hdc_3s1r_cluster>
</clickhouse_remote_servers>

<!-- 本節點副本名稱 (這里只配置單副本)-->
<macros>
   <layer>01</layer>
   <shard>03</shard>
   <replica>hdc-data6</replica>
</macros>

<!-- 監聽網絡 -->
<networks>
  <ip>::/0</ip>
</networks>

<!-- ZK -->
<zookeeper-servers>
 <node index="1">
   <host>hdc-data4</host>
   <port>2181</port>
 </node>
 <node index="2">
   <host>hdc-data5</host>
   <port>2181</port>
 </node>
 <node index="3">
   <host>hdc-data6</host>
   <port>2181</port>
 </node>
</zookeeper-servers>

<!-- 數據壓縮算法 -->
<clickhouse_compression>
<case>
 <min_part_size>10000000000</min_part_size>
 <min_part_size_ratio>0.01</min_part_size_ratio>
 <method>lz4</method>
</case>
</clickhouse_compression>

</yandex>

補充說明:

標簽名 描述
clickhouse_remote_servers 配置分布式表中使用的集群。
hdc_3s1r_cluster 自定義的標簽名,也就是集群名稱。群集名稱不能包含“.”(點)符號。
shard 數據分片標簽,一個shard標簽組代表一個數據分片。
weight 定義數據分片的數據權重。比如有兩個分片,第一個權重為9,第二個權重為10,則該批次的行將會有9/19的數據被發送到第一個分片,10/19的數據被發送到第二分片。
internal_replication 是否啟用內部復制。true 代表寫入數據時選擇第一個健康的副本進行寫入,其余副本以該表本身進行復制,保證復制表的一致性。false(默認) 代表將數據直接寫入所有副本,因為沒有檢查復制表的一致性,而且隨着時間的推移,它們將包含略微不同的數據。
replica 指定分片數據副本,可為每個服務器指定參數主機、端口和可選的用戶、密碼、安全、壓縮等
host 數據分片遠程服務地址(支持IPv6 )。如果指定了域名(domain),服務器在啟動時發出DNS請求並且只要服務器在運行就能一直保存結果。如果DNS請求失敗,服務器不會啟動。如果更改DNS記錄,請重新啟動服務器。
port TCP端口(對應config.xml的"tcp_port",通常設置為9000)。不要將其與http_port混淆。
user 連接到遠程服務器的用戶的名稱。默認值:"default"。此用戶必須具有連接到指定服務器的權限。對應的用戶名和密碼是在user.xml定義。
password 連接到遠程服務器的密碼。默認值:空字符串。根據實際在user.xml中對應用戶的密碼明文
secure 使用ssl進行連接,通常還應該定義端口= 9440。服務器應該監聽9440並且有正確的證書,對應config.xml中“tcp_port_secure”。(示例中無)
compression 開啟數據壓縮,默認True(示例中無)
macros 宏定義。{layer} - ClickHouse集群的昵稱,用於區分不同集群之間的數據。{shard} - 分片編號或符號引用。{replica} - 副本的名稱(唯一),通常與主機名匹配macros為可選定義。配置文件中定義了在創建表時每台服務器就可以使用相同的建表DDL。否則要ReplicatedMergeTree指定zk路徑和replica值。(后面復制表細講)
networks 監聽網絡,::/0代表監聽所有ip
zookeeper-servers ClickHouse在使用復制表時使用ZooKeeper存儲復制元數據。和config.xml文件中<zookeeper incl="xxx">對應
clickhouse_compression ClickHouse檢查{min_part_size}和{min_part_size_ratio},並處理與這些條件匹配的{case}塊。如果<case>不匹配,ClickHouse應用lz4壓縮算法。{method}指壓縮方法,可接受值:lz4或zstd(實驗值)。
2.3.2 修改config.xml配置

/etc/clickhouse-server/config.xml中放開遠程主機監聽

 

    <listen_host>::1</listen_host>
   <listen_host>0.0.0.0</listen_host>

遇到問題:

  1. 登錄時報異常 Code: 210. DB::NetException: Connection refused (localhost:9000, ::1) 解決:需要開放::1。另外zookeeper集群沒有正常啟動也會造成建表時報此類錯誤。

默認路徑為/etc/metrika.xml。若想改變路徑或文件名則需要在/etc/clickhouse-server/config.xml中添加例如下配置:

 

    <include_from>/etc/clickhouse-server/metrica.xml</include_from>
2.3.3 修改用戶配置(user.xml)
  1. 出於安全性考慮,將明文密碼配置`改成加密配置加密密碼生成方式1(隨機生成):PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'加密密碼生成方式2(指定密碼):echo -n "your password" | sha256sum | tr -d '-'`

  2. 在profiles標簽下的readonly標簽添加如下配置:

    img

  3. 示例,添加一個只讀用戶

 

        <ckh_readonly>
           <password_sha256_hex>8545f4dc3fe83224980663ebc2540d6a68288c8afcbaf4da3b22e72212e256e1</password_sha256_hex>
           <networks incl="networks" replace="replace">
               <ip>::/0</ip>
           </networks>
           <profile>readonly</profile>
           <quota>default</quota>
           <allow_databases>
               <database>default</database>
           </allow_databases>
       </ckh_readonly>
2.3.4 重啟集群及查看狀態

img

2.3.5 登錄驗證

 

clickhouse-client -u 'ckh_readonly' --password 'ck10086'

更多參數幫助:clickhouse-client --help

img

改用默認用戶登錄,創建分布式表(建表語句需要在每台數據分片的服務器上都執行一遍,大規模集群通常通過腳本維護)。為何要這樣創建,后面講解。

 

CREATE TABLE ontime_local (FlightDate Date,Year UInt16) ENGINE = MergeTree(FlightDate, (Year, FlightDate), 8192);
CREATE TABLE ontime_all AS ontime_local ENGINE = Distributed(hdc_3s1r_cluster, default, ontime_local, rand());

插入測試數據

 

insert into ontime_all (FlightDate,Year)values('2001-10-12',2001);
insert into ontime_all (FlightDate,Year)values('2002-10-12',2002);
insert into ontime_all (FlightDate,Year)values('2002-10-12',2003);

在任何一台服務器客戶端查詢結果:

 

img

三、表的基本理解和使用

在分布式集群中,我們通常需要先創建本地表(分片表/復制表)再創建分布式表。因為分布式表只是作為一個查詢引擎,本身不存儲任何數據,查詢時將sql發送到所有集群分片,然后進行進行處理和聚合后將結果返回給客戶端。創建什么樣的表,需要根據實際的使用場景決定在創建表指定什么樣的表引擎

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

  • 數據的存儲方式和位置,寫到哪里以及從哪里讀取數據

  • 支持哪些查詢以及如何支持。

  • 並發數據訪問。

  • 索引的使用(如果存在)。

  • 是否可以執行多線程請求。

  • 數據復制參數。

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

首先了解一下建表的幾種方式

Way 1: 常規語法 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

Way 2: 具有相同結構的表,同時可以對其指定不同的表引擎聲明。 CREATE TABLE [IF NOT EXISTS] [db.]table_name AS [db2.]name2 [ENGINE = engine]

Way 3: 使用指定的引擎創建一個與SELECT子句的結果具有相同結構的表,並使用SELECT子句的結果填充。 CREATE TABLE [IF NOT EXISTS] [db.]table_name ENGINE = engine AS SELECT ...

由上可知,ENGINE = ?需要我們對表引擎的了解才能做出選擇。 根據個人的理解以分片表、復制表和分布式表來展開介紹部分表引擎。這里更多的是介紹引擎的特性以便更好地對相應的場景做出選擇。更多可以參考官網。

3.1 分片表 & 表引擎

每個節點都有一個數據子集。重申一遍,每個clickhouse-server實例下對應只能被配置為某個數據分片(shard)的唯一副本(replica)。

分布式高可用方案:分片表+分布式表+集群復制(即一個數據分片(shard)下配置多個副本主機(replica))

 

img

3.1.1 MergeTree引擎

MergeTree引擎及其家族(*MergeTree)的其他引擎是ClickHouse健壯性最強的表引擎。 MergeTree主要特性:

  • 存儲按住鍵排序的數據 允許創建一個小的稀疏索引來幫助快速查詢數據

  • 允許在指定分區鍵時使用分區

  • 支持數據復制

  • 支持數據采樣

使用方式1 示例:

ENGINE MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192 說明: ENGINE ——指定引擎類型

PARTITION BY——指點分區字段(可選)。對於按月分區的表,日期字段需格式化為“YYYYMM”,轉換函數:toYYYYMM(date_column)。通常該字段需為Date類型 ORDER BY——指定排序字段(可選),tuple類型。例如:ORDER BY (CounterID, EventDate) PRIMARY KEY——指定主鍵字段(可選)。通常主鍵默認和排序(ORDER BY)字段相同,不需另外指定。 SAMPLE BY——抽樣的表達式(可選),表達式(列)必須被主鍵包含,例如:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID)) SETTINGS——控制合並樹的其他參數設置(可選)。index_granularity——索引的粒度。索引“標記”之間的數據行數。默認值:8192。

使用方式2 示例:

ENGINE = MergeTree(PARTITION column, (ORDER BY column), 8192);

MergeTree家族的引擎需要使用Date類型的列來指定分區。

3.1.2 ReplacingMergeTree引擎

繼承自MergeTree。ReplacingMergeTree與MergeTree的不同之處在於,它刪除具有相同主鍵值的重復條目。重復數據刪除僅在合並期間發生,並且合並發生在一個未知的時間。因此,ReplacingMergeTree適合清除后台的重復數據以節省空間,但並不保證沒有重復數據。

ENGINE = ReplacingMergeTree([ver]) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...] 說明:ver——列版本,輸入類型UInt*、Date或DateTime,可選參數。其他參照MergeTree參數說明。

3.1.3 SummingMergeTree引擎

繼承自MergeTree。不同之處在於,當合並SummingMergeTree表的數據部分時,ClickHouse將所有具有相同主鍵的行替換為一行,該行包含數字數據類型的列的匯總值。如果主鍵的組合方式是單個鍵值對應於大量行,這將顯著減少存儲容量並加快數據選擇。

ENGINE = SummingMergeTree() [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]

體現在select的時候使用sum(columns )和group by 。columns 必須是數字類型,並且不能在主鍵中。如果不指定columns,ClickHouse用非主鍵的數字數據類型總結了所有列中的值。

3.1.4 AggregatingMergeTree引擎

繼承自MergeTree,改變了數據部件合並的邏輯。ClickHouse用存儲聚合函數狀態組合的單個行(在一個數據部分內)替換所有具有相同主鍵的行。

ENGINE = AggregatingMergeTree() [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]

物化視圖示例:

CREATE MATERIALIZED VIEW test.basic ENGINE = AggregatingMergeTree() PARTITION BY toYYYYMM(StartDate) ORDER BY (CounterID, StartDate) AS SELECT CounterID, StartDate, sumState(Sign) AS Visits, uniqState(UserID) AS Users FROM test.visits GROUP BY CounterID, StartDate; 說明:寫入數據到test.visits表 時,同時生產聚合寫入到視圖。可以通過如下語句查詢聚合結果: SELECT StartDate, sumMerge(Visits) AS Visits, uniqMerge(Users) AS Users FROM test.basic GROUP BY StartDate ORDER BY StartDate;

3.1.5 CollapsingMergeTree引擎

承自MergeTree,將行瓦解/折疊的邏輯添加到數據部件合並算法中。如果一行中的所有字段都是等效的,除具有1和-1值的特定字段符號外,則會異步刪除(瓦解/折疊)行等效字段。該引擎可以顯著減少存儲容量,提高SELECT查詢的效率。

ENGINE = CollapsingMergeTree(sign) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...] 說明:sign——如果Sign = 1表示行是對象的狀態,我們稱之為“state”行。如果符號= -1表示取消具有相同屬性的對象的狀態,我們稱之為“cancel”行。列數據類型- Int8。

例如數據: ┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 5 │ 146 │ 1 │ │ 4324182021466249494 │ 5 │ 146 │ -1 │ │ 4324182021466249494 │ 6 │ 185 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘

  • 表結構如下: CREATE TABLE UAct ( UserID UInt64, PageViews UInt8, Duration UInt8, Sign Int8 ) ENGINE = CollapsingMergeTree(Sign) ORDER BY UserID

  • 我們可以通過聚合獲取結果: SELECT UserID, sum(PageViews * Sign) AS PageViews, sum(Duration * Sign) AS Duration FROM UAct GROUP BY UserID HAVING sum(Sign) > 0 ┌──────────────UserID─┬─PageViews─┬─Duration─┐ │ 4324182021466249494 │ 6 │ 185 │ └─────────────────────┴───────────┴──────────┘

  • 如果不需要聚合並希望強制折疊,可以FINAL修飾符。 SELECT * FROM UAct FINAL ┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 6 │ 185 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘

3.1.6 VersionedCollapsingMergeTree引擎

承自MergeTree,並將行折疊的邏輯添加到數據部件合並算法中。VersionedCollapsingMergeTree解決了與CollapsingMergeTree相同的問題,但是使用了另一種折疊算法。它允許使用多個線程以任意順序插入數據。特定的Version列有助於正確地折疊行,即使它們以錯誤的順序插入。折疊合並樹只允許嚴格連續的插入。

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

  • 刪除后台對象的舊狀態。它會導致存儲容量的顯著減少。

3.1.7 Log引擎家族

這些引擎是為需要使用少量數據(少於100萬行)編寫許多表的場景而開發的。

3.2 復制表 & 復制表引擎

復制表用於在不同服務器上存儲數據的多個副本, 嚴重依賴Zookeeper(ZooKeeper 3.4.5+),不同的Zookeeper路徑允許支持不同的復制拓撲。由於很難為每個節點的每個表創建自定義路徑,因此ClickHouse提供了宏替換機制。宏在每個節點的配置文件中定義(為此目的使用單獨的文件是有意義的,例如/etc/clickhouseserver/macros.xml)並在大括號中引用。對於復制表,宏參與兩個地方:

  • Zookeeper中表的znode的路徑

  • 副本名稱具有相同ZooKeeper路徑的表將是特定數據分片的副本。插入可以轉到任何副本,ClickHouse接管復制以確保所有副本處於一致狀態。插入不強制一致性,復制是異步的。可以使用不同的Zookeper路徑模擬不同的復制拓撲。

例如宏配置如下所示:

<macros> <layer>05</layer> <shard>02</shard> <replica>xxxx</replica> </macros>

在此示例中定義了3個宏: {layer} - ClickHouse集群的昵稱,用於區分不同集群之間的數據。 {shard} - 分片編號或符號引用 {replica} - 副本的名稱,通常與主機名匹配

這樣在創建復制表時就可以直接使用宏定義而不用在不同的服務器創建表時都要修改對應的zk路徑和副本({replica})標識,例如:

ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/<tablename_of_node_in_zk>','{replica}', <date_partition_column>, (sort columns), 8192)

分布式高可用方案:復制表+分布式表

 

img

說明: 1、復制表的副本和配置文件中配置shard下的replica無關。換句話說,數據備份與分片沒有必然聯系。 2、zookeeper與select查詢無關,因為查詢性能與復制無關。復制表的查詢性能和非復制表一樣。 3、復制是異步和多主機的。INSERT查詢(以及ALTER)可以發送到任何可用的服務器。在運行查詢的服務器上插入數據,然后將數據復制到其他服務器。因為它是異步的,所以最近插入的數據會出現在其他副本上,有一些延遲。如果部分副本不可用,則在它們可用時寫入數據。如果副本可用,則延遲是通過網絡傳輸壓縮數據塊所需的時間。 4、數據塊作為原子單位,INSERT被划分為max_insert_block_size = 1048576行的塊。 5、在復制期間,僅通過網絡傳輸要插入的源數據。進一步的數據轉換(合並)以相同的方式在所有副本上協調和執行。 6、系統監視副本上的數據同步性,並能夠在失敗后恢復。故障轉移是自動的(對於數據的微小差異)或半自動的(當數據差異過大時,這可能表明存在配置錯誤)。

另外,復制表目前只有MergeTree引擎家族中以下引擎支持:

  • ReplicatedMergeTree

  • ReplicatedSummingMergeTree

  • ReplicatedReplacingMergeTree

  • ReplicatedAggregatingMergeTree

  • ReplicatedCollapsingMergeTree

  • ReplicatedGraphiteMergeTree

3.3 分布式表 & Distributed引擎

分布式表用於使用單個表接口訪問位於不同服務器的表(數據分片)。分布式表由“分布式”引擎定義,實際上是分片表上的接口。建議進行客戶端分割,並將數據插入ClickHouse節點上的本地切分表中。但是,也可以直接插入到分布式表中。 在一個ClickHouse系統中,可以使用不同的集群,例如,有些表可以不復制地分片,有些表可以復制,等等。還可以在“子集群”中存儲一些數據,但可以通過全局分布式表訪問它們。

將分布式表視為一個接口更容易。建議進行客戶端分段並將數據插入到ClickHouse節點上的本地分片表中。但是,也可以直接插入分布式表中,ClickHouse使用分片鍵頂部的哈希函數分發數據。

集群配置可以動態更新。因此,如果向分布式表中添加新節點,則不需要重新啟動服務器。如果需要將單個節點表擴展到多個服務器,則過程如下:

  1. 在新服務器上創建分片表

  2. 必要時重新分發數據(手動更好,但ClickHouse也支持重新分片)

  3. 定義集群配置並將其放在每個ClickHouse節點上

  4. 創建分布式表以訪問多個分片中的數據

ENGINE = Distributed(<cluster>, <database>, <shard table> [, sharding_key])

3.4 其他常用引擎
3.4.1MySQL 引擎

對存儲在遠程 MySQL 服務器上的數據執行 SELECT 查詢。

調用格式:

MySQL('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_duplicate_clause']);

調用參數

  • host:port — MySQL 服務器地址。

  • database — 數據庫的名稱。

  • table — 表名稱。

  • user — 數據庫用戶。

  • password — 用戶密碼。

  • replace_query — 將 INSERT INTO 查詢是否替換為 REPLACE INTO 的標志。如果 replace_query=1,則替換查詢

  • 'on_duplicate_clause' — 將 ON DUPLICATE KEY UPDATE 'on_duplicate_clause' 表達式添加到 INSERT 查詢語句中。例如:impression = VALUES(impression) + impression。如果需要指定 'on_duplicate_clause',則需要設置 replace_query=0。如果同時設置 replace_query = 1'on_duplicate_clause',則會拋出異常。

此時,簡單的 WHERE 子句(例如 =, !=, >, >=, <, <=)是在 MySQL 服務器上執行。

其余條件以及 LIMIT 采樣約束語句僅在對MySQL的查詢完成后才在ClickHouse中執行。

MySQL 引擎不支持 Nullable 數據類型,因此,當從MySQL表中讀取數據時,NULL 將轉換為指定列類型的默認值(通常為0或空字符串)。

3.4.2 Kafka引擎

ClickHouse結合Kafka使用。

Kafka SETTINGS kafka_broker_list = 'localhost:9092', kafka_topic_list = 'topic1,topic2', kafka_group_name = 'group1', kafka_format = 'JSONEachRow', kafka_row_delimiter = '\n', kafka_schema = '', kafka_num_consumers = 2

示例:

CREATE TABLE queue ( timestamp UInt64, level String, message String ) ENGINE = Kafka('localhost:9092', 'topic', 'group1', 'JSONEachRow');

SELECT * FROM queue LIMIT 5;

CREATE TABLE queue2 ( timestamp UInt64, level String, message String ) ENGINE = Kafka SETTINGS kafka_broker_list = 'localhost:9092', kafka_topic_list = 'topic', kafka_group_name = 'group1', kafka_format = 'JSONEachRow', kafka_num_consumers = 4;

四、性能測試

本次測試基於虛擬機搭建的集群。性能方面有影響,只做參考。 你可以使用官網的數據進行測試,具體查看https://clickhouse.yandex/docs/en/single/?query=internal_replication#import-from-raw-data 本次測試示例將從mysql表中導入數據到clickhouse。首先創建本地表和分布式表(使用ON CLUSTER就不用再每一台服務器執行下面的建表DDL),表結構如下(這里只列出部分列,總列數63):

 

CREATE TABLE demo.elec_meter_data ON CLUSTER hdc_3s1r_cluster(
 `id` Int64,
 `loc_id` Int64,
 `gw_id` Int32,
 `meter_id` Int32,
 `zxygz` Decimal(20,4),
 `dya` Decimal(20,4),
 `dyb` Decimal(20,4),
 `dyc` Decimal(20,4),
 `dla` Decimal(20,4),
 `dlb` Decimal(20,4),
 `dlc` Decimal(20,4),
 `ygglz` Decimal(12,4),
 `date_time` DateTime,
 `create_time` DateTime
) ENGINE=MergeTree()
ORDER BY (id);

注意:The MySQL engine does not support the Nullable data type, so when reading data from MySQL tables, NULL is converted to default values for the specified column type (usually 0 or an empty string). 嘗試建表時指定默認值對於mysql的null值,依然報:Cannot convert NULL value to non-Nullable type...

創建分布式表(每台集群機器執行)

 

CREATE TABLE demo.elec_meter_data_all AS demo.elec_meter_data ENGINE = Distributed(hdc_3s1r_cluster, demo, elec_meter_data, rand());

 

INSERT INTO demo.elec_meter_data_all (
`id`,
`loc_id`,
`gw_id`,
`meter_id`,
`zxygz`,
`dya`,
`dyb`,
`dyc`,
`dla`,
`dlb`,
`dlc`,
`ygglz`,
`date_time`,
`create_time`)
SELECT `id`,
`loc_id`,
`gw_id`,
`meter_id`,
`zxygz`,
`dya`,
`dyb`,
`dyc`,
`dla`,
`dlb`,
`dlc`,
`ygglz`,
`date_time`,
`create_time`
FROM mysql('host:port', 'database_name', 'table_name', 'username', 'password');

img

select count() from elec_meter_data_all;

 

img

select * from elec_meter_data_all where meter_id=190

 

img

select * from elec_meter_data_all where meter_id=190 limit 3000;

 

img

select id,meter_id,zxygz,date_time from elec_meter_data_all where meter_id=190;

 

img

SELECT id,meter_id,zxygz,date_time FROM elec_meter_data_all WHERE meter_id GLOBAL IN (SELECT DISTINCT(meter_id) as meter_id FROM equip_meter_all WHERE equip_id=10066) limit 1000;

五、常見問題

內存不足,調整配置(僅參考)

<max_memory_usage>100000000000</max_memory_usage> <max_bytes_before_external_group_by>50000000000</max_bytes_before_external_group_by> <max_bytes_before_external_sort>80000000000</max_bytes_before_external_sort> <distributed_aggregation_memory_efficient>1</distributed_aggregation_memory_efficient>

第二章、clickhouse實戰

 


免責聲明!

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



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