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配置項(服務端配置)
users.xml配置項(可用最大內存配置等,大部分配置在users.xml)
 

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 倍。
 
 
 
 


免責聲明!

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



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