ClickHouse 高階(二)建表優化
阿新 • • 發佈:2021-08-08
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 ) engine1.2 空值儲存型別 官方已經指出 Nullable 型別幾乎總是會拖累效能,因為儲存 Nullable 列時需要建立一個額外的檔案來儲存 NULL 的標記,並且 Nullable 列無法被索引。因此除非極特殊情況,應直 接使用欄位預設值表示空,或者自行指定一個在業務中無意義的值(例如用-1 表示沒有商品ID)。=ReplacingMergeTree(create_time) partition by toYYYYMMDD(toDate(create_time)) –-需要轉換一次,否則報錯 primary key (id) order by (id, sku_id);
CREATE檢視儲存的檔案:(沒有許可權就用 root 使用者) 官網說明:https://clickhouse.tech/docs/zh/sql-reference/data-types/nullable/TABLE t_null(x Int8, y Nullable(Int8)) ENGINE TinyLog; INSERT INTO t_null VALUES (1, NULL), (2, 3); SELECT x + y FROM t_null;
2 分割槽和索引
分割槽粒度根據業務特點決定,不宜過粗或過細。一般選擇按天分割槽,也可以指定為 Tuple(),以單表一億資料為例,分割槽大小控制在 10-30 個為最佳。 必須指定索引列,ClickHouse 中的索引列即排序列…… 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.4.5 資料 TTL)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 引數 來實現。