一、名字由来
MergeTree 在写入一批数据时,数据总会以数据片段的形式写入磁盘,且数据片段不可修改。为避免片段过多,ClickHouse 会通过后台线程定期合并这些数据片段,属于相同分区的数据片段会被合成一个新的片段。这种数据片段往复合并的特点也正是合并树的名称由来。
二、建表解析
...
)ENGING = MergeTree()
[PARTITION BY expr] # 分区键
[ORDER BY expr] # 排序键 MergeTree引擎的关键参数
[PRIMARY KEY expr] # 主键 一级索引
[SAMPLE BY expr]
[SETTINGS name=value, ...] index_granularity=8192 索引粒度
- 指定ORDER BY 参数后,在每个分区里,数据是有序的,但所有分区不一定有序(局部有序)
- PRIMARY KEY 通常可以不填,因为 ORDER BY 可以作为主键;当用户需要主键的顺序与分区的顺序不一样时,则需要设置 PRIMARY KEY
- CK的所有数据,都以分区的形式被组织
三、文件目录
四、数据分区
数据的分区规则
-
不指定分区键
如果不使用分区键,既不使用PARTITION BY声明任何分区表达式,则分区ID默认取名为all,所有的数据都会被写入到这个all分区
-
使用整型
如果分区键取值属于整型,且无法转换为日期类型YYYYMMDD格式,则直接按照该类型的字符形式输出作为分区ID的取值
-
使用日期类型
如果分区键取值类型属于日期类型,或者是能够转换为YYYYMMDD日期格式的整型,则使用按照YYYYMMDD日期格式化后的字符形式输出作为分区ID的取值
-
使用其他类型
如果分区键取值既不属于整型,也不属于日期类型,例如 String、Float 等,则通过128位Hash算法取其Hash值作为分区ID的取值
分区目录的命名规则
分区目录文件案例
201905_1_1_0
201905_2_2_0
201905_3_3_0
201905_4_4_0
分区目录文件名组成方式:PartitionID_MinBlockNum_MaxBlockNum_Level
-
PartitionID
分区ID
-
MinBlockNum 和 MaxBlockNum
最小数据块编号和最大数据块编号,
BlockNum
是一个整型自增长编号(记作n),其在单张MergeTree
数据表内全局累加,n从1开始,每当新创建一个分区目录时,计数n就会累加1,对于一个新的分区目录而言,MinBlockNum
和MaxBlockNum
取值一样,同等于n -
Level
合并的层级,可以理解为某个分区被合并过的次数。初始值为0,之后以分区为单位,如果相同分区发生合并动作,则相应分区内计数累加1
以日期作为分区的表,分3次insert,写入了三条数据,此时会生成3个目录
201905_1_1_0
201905_2_2_0
201906_3_3_0
其中第一和第二是同一个分区,可进行合并
--> 201905_1_2_1 (最小BlockNum为1,最大BlockNum为1,合并次数1)
此时又进行了一次insert操作
201905_4_4_0
属于同一个分区,和 201905_1_2_1 合并
--> 201905_1_4_2
五、一级索引和二级索引
稠密索引
一个索引对应一行数据
稀疏索引
一个索引标记对应一块或一个区间的数据,在ck中,一个索引标记对应8192(索引粒度)行数据;一级索引可理解为书的目录,它是常驻内存的