1. 程式人生 > 其它 >ClickHouse-優化(建表、配置)

ClickHouse-優化(建表、配置)

1.資料型別

1.1時間欄位的型別

建表時能用數值型或日期時間型表示的欄位就不要用字串,全 String 型別在以 Hive為中心的數倉建設中常見,但 ClickHouse 環境不應受此影響。 雖然 ClickHouse 底層將 DateTime 儲存為時間戳 Long 型別,但不建議儲存 Long 型別,因為 DateTime 不需要經過函式轉換處理,執行效率高、可讀性好。
CREATE TABLE t_type2
(
    `id` UInt32,
    `sku_id` String,
    `total_amount` Decimal(16, 2),
    `create_time` Int32
)
ENGINE 
= ReplacingMergeTree(create_time) PARTITION BY toYYYYMMDD(toDate(create_time)) —-此處需要轉換成時間型別 PRIMARY KEY id ORDER BY (id, sku_id); CREATE TABLE t_type3 ( `id` UInt32, `sku_id` String, `total_amount` Decimal(16, 2), `create_time` DateTime ) ENGINE = ReplacingMergeTree(create_time) PARTITION BY toYYYYMMDD(create_time) PRIMARY KEY id ORDER BY (id, sku_id);

 

1.2空值儲存型別

官方已經指出 Nullable 型別幾乎總是會拖累效能,因為儲存 Nullable 列時需要建立一個額外的檔案來儲存 NULL 的標記,並且 Nullable 列無法被索引。因此除非極特殊情況,應直接使用欄位預設值表示空,或者自行指定一個在業務中無意義的值(例如用-1 表示沒有商品ID)。
date1002 :) CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE TinyLog;
CREATE TABLE t_null
(
    `x` Int8,
    `y` Nullable(Int8)
)
ENGINE 
= TinyLog Query id: 4a313cb8-86a7-4bf0-99a9-16a945e665ac Ok. 0 rows in set. Elapsed: 0.003 sec. date1002 :) INSERT INTO t_null VALUES (1, NULL), (2, 3); INSERT INTO t_null FORMAT Values Query id: ebd34cde-af7a-46e4-8956-b2ddc8afc09b Ok. 2 rows in set. Elapsed: 0.002 sec. date1002 :) SELECT x + y FROM t_null; SELECT x + y FROM t_null Query id: fe7448ca-2147-43ac-8afe-725852577fe0 ┌─plus(x, y)─┐ │ ᴺᵁᴸᴸ │ │ 5 │ └────────────┘
  檢視儲存的檔案
[root@date1002 ~]# cd /var/lib/clickhouse/data/default/t_null/
[root@date1002 t_null]# ll
總用量 16
-rw-r----- 1 clickhouse clickhouse 95 4月  20 22:06 sizes.json
-rw-r----- 1 clickhouse clickhouse 28 4月  20 22:06 x.bin
-rw-r----- 1 clickhouse clickhouse 28 4月  20 22:06 y.bin
-rw-r----- 1 clickhouse clickhouse 28 4月  20 22:06 y.null.bin
y欄位可以為null的話,會有一個檔案單獨儲存null值  

2.分割槽和索引

分割槽粒度根據業務特點決定,不宜過粗或過細。一般選擇按天分割槽,也可以指定為 Tuple(),以單表一億資料為例,分割槽大小控制在 10-30 個為最佳。 必須指定索引列,ClickHouse 中的索引列即排序列,通過 order by 指定,一般在查詢條件中經常被用來充當篩選條件的屬性被納入進來;可以是單一維度,也可以是組合維度的索引;通常需要滿足高階列在前、查詢頻率大的在前原則;還有基數特別大的不適合做索引列,如使用者表的 userid 欄位;通常篩選後的資料滿足在百萬以內為最佳。   比如官方案例的 hits_v1 表:
……
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
……
visits_v1 表:
……
PARTITION BY toYYYYMM(StartDate)
ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)
……
 

3.表引數

Index_granularity 是用來控制索引粒度的,預設是 8192,如非必須不建議調整。 如果表中不是必須保留全量歷史資料,建議指定 TTL(生存時間值),可以免去手動過期歷史資料的麻煩,TTL 也可以通過 alter table 語句隨時修改。  

4.寫入和刪除優化

(1)儘量不要執行單條或小批量刪除和插入操作,這樣會產生小分割槽檔案,給後臺Merge 任務帶來巨大壓力 (2)不要一次寫入太多分割槽,或資料寫入太快,資料寫入太快會導致 Merge 速度跟不上而報錯,一般建議每秒鐘發起 2-3 次寫入操作,每次操作寫入 2w~5w 條資料(依伺服器效能而定)   寫入過快報錯,報錯資訊: 1. Code: 252, e.displayText() = DB::Exception: Too many parts(304).Merges are processing significantly slower than inserts 2. Code: 241, e.displayText() = DB::Exception: Memory limit (for query) exceeded:would use 9.37 GiB (attempt to allocate chunk of 301989888 bytes), maximum: 9.31 GiB 處理方式: Too many parts 處理:使用 WAL 預寫日誌,提高寫入效能。 in_memory_parts_enable_wal 預設為 true 在伺服器記憶體充裕的情況下增加記憶體配額,一般通過 max_memory_usage 來實現 在伺服器記憶體不充裕的情況下,建議將超出部分內容分配到系統硬碟上,但會降低執行速度,一般通過 max_bytes_before_external_group_by、max_bytes_before_external_sort 引數來實現。  

5.常見配置

配置項主要在 config.xml 或 users.xml 中, 基本上都在 users.xml 裡 config.xml配置項(服務端配置) https://clickhouse.com/docs/en/operations/server-configuration-parameters/settings/ users.xml配置項(可用最大記憶體配置等,大部分配置在users.xml) https://clickhouse.com/docs/en/operations/settings/settings/  

5.1CPU資源

background_pool_size:後臺執行緒池的大小,merge 執行緒就是在該執行緒池中執行,該執行緒池不僅僅是給 merge 執行緒用的,預設值 16,允許的前提下建議改成 cpu 個數的 2 倍(執行緒數)。 background_schedule_pool_size:執行後臺任務(複製表、Kafka 流、DNS 快取更新)的執行緒數。預設 128,建議改成 cpu 個數的 2 倍(執行緒數)。 background_distributed_schedule_pool_size:設定為分散式傳送執行後臺任務的執行緒數,預設 16,建議改成 cpu個數的 2 倍(執行緒數)。 max_concurrent_queries:最大併發處理的請求數(包含 select,insert 等),預設值 100,推薦 150(不夠再加)~300。 max_threads:設定單個查詢所能使用的最大 cpu 個數,預設是 cpu 核數  

5.2記憶體資源

max_memory_usage: 此引數在 users.xml 中,表示單次 Query 佔用記憶體最大值,該值可以設定的比較大,這樣可以提升叢集查詢的上限。保留一點給 OS,比如 128G 記憶體的機器,設定為 100GB。 max_bytes_before_external_group_by:一般按照 max_memory_usage 的一半設定記憶體,當 group 使用記憶體超過閾值後會重新整理到磁碟進行。因為 clickhouse 聚合分兩個階段:查詢並及建立中間資料、合併中間資料,結合上一項,建議 50GB。 max_bytes_before_external_sort :當 order by 已使用 max_bytes_before_external_sort 記憶體就進行溢寫磁碟(基於磁碟排序),如果不設定該值,那麼當記憶體不夠時直接拋錯,設定了該值 order by 可以正常完成,但是速度相對存記憶體來說肯定要慢點(實測慢的非常多,無法接受)。 max_table_size_to_drop: 此引數在 config.xml 中,應用於需要刪除表或分割槽的情況,預設是50GB,意思是如果刪除 50GB 以上的分割槽表會失敗。建議修改為 0,這樣不管多大的分割槽表都可以刪除。  

5.3儲存

ClickHouse 不支援設定多資料目錄,為了提升資料 io 效能,可以掛載虛擬卷組,一個卷組繫結多塊物理磁碟提升讀寫效能,多資料查詢場景 SSD 會比普通機械硬碟快 2-3 倍。