mergeTree
數(shù)據(jù)存儲(chǔ)方式
數(shù)據(jù)庫(kù)表在clickhouse中是分塊存儲(chǔ)(如果 partitioning key 存在則使用定義的鍵分塊)绎谦,每一塊又分為文件存儲(chǔ)理逊,每一塊的存儲(chǔ)方式有2中wide和compact窿侈。
wide: 每一列存一個(gè)單獨(dú)的文件
compact: 所有列都存在一個(gè)文件中扼雏。compact格式可以提高插入量少插入頻率頻繁時(shí)的性能屿岂。
存儲(chǔ)方式由min_bytes_for_wide_part和min_rows_for_wide_part控制。如果這兩個(gè)參數(shù)都未設(shè)置則作郭,默認(rèn)為wide。
每一塊存儲(chǔ)在邏輯上又拆分為顆粒弦疮。顆粒的配置參數(shù)為index_granularity 和index_granularity_bytes夹攒。
主鍵
- 主鍵可以重復(fù)
- 主鍵可以是多列的組合
- 主鍵選擇依據(jù)是該列上有查詢條件,并且查詢條件可過濾掉的數(shù)據(jù)量越大那么主鍵的索引效率就越高胁塞。因?yàn)槭褂弥麈I排序咏尝,主鍵的一致性越高,壓縮就越大啸罢。在 CollapsingMergeTree 和SummingMergeTree引擎中將排序字段作為主鍵可以提供額外的邏輯编检。
- 主鍵越長(zhǎng)會(huì)影響插入效率和內(nèi)存使用。
- 如果未指明主鍵扰才,則使用sort by 的數(shù)據(jù)作為主鍵允懂。
主鍵和排序鍵不同的意義
這經(jīng)常發(fā)生在SummingMergeTree和AggregatingMergeTree中,因?yàn)檫^濾條件where和聚集條件group by很可能不一樣衩匣。所以主鍵通過where條件選擇蕾总,排序鍵根據(jù)group by選擇。保證了插入和集合的效率琅捏。
索引選擇
根據(jù)where或者prewhere條件匹配程度選擇索引生百,包括in條件,前部分固定的like語(yǔ)句(不以%開頭)柄延,主鍵置侍,分區(qū)鍵,列的重復(fù)方法拦焚,以及上述條件的邏輯關(guān)系。
分區(qū)鍵即是作為分區(qū)查詢的依據(jù)杠输,也需要在主鍵中引入赎败,不然在分區(qū)內(nèi)部無法有效查詢。
--ENGINE MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate) SETTINGS index_granularity=8192
--不走所有
SELECT count() FROM table WHERE CounterID = 34 OR URL LIKE '%upyachka%'
部分單調(diào)主鍵蠢甲。如1-30日在1個(gè)月中是單調(diào)函數(shù)僵刮,但在更長(zhǎng)的期間不是。如果查詢范圍剛好在這個(gè)月那么clickhouse會(huì)使用這個(gè)索引鹦牛,如果查詢條件不包含單調(diào)序列區(qū)間搞糕,則進(jìn)行全表掃描。
數(shù)據(jù)跳躍索引
-- 語(yǔ)法
INDEX index_name expr TYPE type(...) GRANULARITY granularity_value
--示例
CREATE TABLE table_name
(
u64 UInt64,
i32 Int32,
s String,
...
INDEX a (u64 * i32, s) TYPE minmax GRANULARITY 3,
INDEX b (u64 * length(s)) TYPE set(1000) GRANULARITY 4
) ENGINE = MergeTree()
...;
--查詢示例
SELECT count() FROM table WHERE s < 'z';
SELECT count() FROM table WHERE u64 * i32 == 10 AND u64 * length(s) >= 1234;
其中type
minmax: 和主鍵查詢等效
set(max_rows)
ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)
tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)
bloom_filter([false_positive])
其中后三者使用bloom索引曼追,可以優(yōu)化 like '%test%'
mergetree
mergeTree | Replication | 作用 |
---|---|---|
MergeTree | ReplicatedMergeTree | |
ReplacingMergeTree | ReplicatedReplacingMergeTree | 數(shù)據(jù)合并階段用替代方式合并排序鍵相同的數(shù)據(jù)窍仰,用于保證存儲(chǔ)空間,不保證數(shù)據(jù)不重復(fù) |
SummingMergeTree | ReplicatedSummingMergeTree | 數(shù)據(jù)合并階段用合計(jì)方式合并排序鍵相同的數(shù)據(jù)礼殊,用于提高聚合效率 |
AggregatingMergeTree | ReplicatedAggregatingMergeTree | 數(shù)據(jù)合并階段用組合的聚合函數(shù)方式合并排序鍵相同的數(shù)據(jù) |
CollapsingMergeTree | ReplicatedCollapsingMergeTree | 數(shù)據(jù)合并階段用折疊(抵消)方式合并排序鍵相同的數(shù)據(jù)驹吮,用于減少更新操作针史,clickhouse更新操作很昂貴(最初版本不支持更新) |
VersionedCollapsingMergeTree | ReplicatedVersionedCollapsingMergeTree | 通過版本控制刪除舊版本數(shù)據(jù),比CollapsingMergeTree多了版本列 |
GraphiteMergeTree | ReplicatedGraphiteMergeTree | 存儲(chǔ)監(jiān)控工具graphite數(shù)據(jù) |
只能在單獨(dú)的服務(wù)器上運(yùn)行的命令:CREATE, DROP, ATTACH, DETACH, RENAME
clickhouse 集群使用zookeeper
集群的時(shí)候建議插入頻率每秒不超過一次
插入語(yǔ)句只等待1個(gè)服務(wù)的操作碟狞,單這個(gè)服務(wù)異常退出的時(shí)候啄枕,插入數(shù)據(jù)會(huì)丟失,保證多副本確認(rèn)可使用insert_quorum
分區(qū)
數(shù)據(jù)插入是存在單獨(dú)的分區(qū)族沃,然后按分區(qū)鍵進(jìn)行數(shù)據(jù)合并频祝。合并是周期性進(jìn)行了10-15分鐘。還有非周期性執(zhí)行命令OPTIMIZE,但不能依賴此命令(應(yīng)該是異步的)脆淹。
--查詢分區(qū)
SELECT
partition,
name,
active
FROM system.parts
WHERE table = 'visits'
--立即優(yōu)化
OPTIMIZE TABLE visits PARTITION 201902;
舉例
summingMergeTree舉例
CREATE TABLE summtt
(
key UInt32,
value UInt32
)
ENGINE = SummingMergeTree()
ORDER BY key;
INSERT INTO summtt Values(1,1),(1,2),(2,1);
INSERT INTO summtt Values(1,1),(1,2),(2,1);
SELECT * FROM summtt;
--執(zhí)行結(jié)果如下
┌─key─┬─value─┐
│ 1 │ 1 │
│ 1 │ 2 │
│ 2 │ 1 │
└─────┴───────┘
┌─key─┬─value─┐
│ 1 │ 1 │
│ 1 │ 2 │
│ 2 │ 1 │
└─────┴───────┘
6 rows in set. Elapsed: 0.090 sec.
optimize table summtt partition tuple();
SELECT * FROM summtt;
┌─key─┬─value─┐
│ 1 │ 6 │
│ 2 │ 2 │
└─────┴───────┘