赞
踩
Clickhouse 为什么做查询分析那么快????????
因为clickhouse使用了下列方案:
结合两个需求场景来解析
关于表分区目录结构:MergeTree表的分区目录物理结构:
假设有一个分区表:该表有 a,b,date,name四个字段,其中date是分区字段(按月份)
那么对于分区有两个问题:
1.1命名规则 & 合并规则
PartitionID_MinBlockNum_MaxBlockNum_level,示例:20230519_1_1_0
PartitionID:分区字段的值
MinBlockNum:最小块序号
MaxBlockNum:最大块序号
Level:参与合并的次数
BlockNum是表内部全局累加,每次创建一个新的分区目录,就会累加 1
文件目录的变化过程
- -- 假设有两条语句
- A: insert into table values ('2021-06', 'a'), ('2021-07', 'b');
- B: insert into table values ('2021-06', 'c'), ('2021-07', 'd');
语句执行完成后,就会创建如下文件夹
- # 结果体现了blockNum的表内全局累加
- A语句 创建文件夹:2021-06_1_1_0, 2021-07_2_2_0
- B语句 创建文件夹:2021-06_3_3_0, 2021-07_4_4_0
这里就会有疑问,我两条语句向同一个分区写入数据,创建两个目录岂不是增加了没必要目录数量?且增加了很多小文件?
这其实也是为什么说clickhouse不适合单条或少量数据高频写入了,因为clickhouse是通过分区文件合并来整合目录的!当要整合的目录过多,会极大消耗系统的IO资源。
- # 文件目录合并结果
- 2021-06_1_1_0 + 2021-06_3_3_0 = 2021-06_1_3_1
- 2021-07_2_2_0 + 2021-07_4_4_0 = 2021-07_2_4_1
这里再重温一下文件夹命名规则:ParitionID_MinBlockNum_MaxBlockNum_level
通过结果可以很直观的看出,同一个分区多目录合并时,会取最小的blockNum 与 最大的blockNum作为批次号,同时会取 max(level) + 1的方式记录合并次数
各文件的含义
- # 文件目录
- ## 以下是数据列存储的文件,其中bin是数据内容,mrk是标记文件,结合索引标记数据位置
- a.bin
- a.mrk2
- b.bin
- b.mrk2
- date.bin
- date.mrk2
- name.bin
- name.mrk2
-
- ## 以下是系统数据文件
- checksums.txt # 校验文件完整性,二进制存储(primary.idx, count.txt)size大小及size哈希值
- columns.txt # 列信息
- primary.idx # 一级索引,主键索引
- minmax_date.idx # 二级索引,分区字段索引
- default_compression_codec.txt # 压缩编码
- count.txt # 当前分区的数据量
文件目录时序图
所有的OLAP技术,基本都是使用的列式存储。其有以下有点:
注意:列式存储,一般不用于数据删除场景,这是列式存储并不擅长做的事情。
在clickhouse中,主键索引默认 8192 条数据作为一条索引
关于一级索引:MergeTree的主键使用 Primary Key 定义,待主键定义后,MergeTree 会根据index_granularity间隔(默认8192条),为数据表生成一级索引并保存至 primary.idx文件
clickhouse中二级索引是在一级索引的基础上建立的,有一个重要的参数:
granularity = 3 这个的意思是:在3段一级索引上创建二级索引
二级索引支持的类型
关于数据压缩:clickhouse的数据存储文件column.bin 中存储的是一列数据,由于一列是相同的数据类型,所以方便高效压缩,在进行压缩的实时,请注意:一个压缩数据块由头信息和压缩数据两部分组成,头信息固定使用9位字节表示,具体有 1 个 UInt8(1字节)整型和2个UInt32(4字节)整型组成,分别代表使用的压缩算法类型、压缩后的数据大小和压缩前的数据大小。每个压缩数据块的体积,按照其压缩前 max_compress_block_size(默认1MB)参数指定
原理说法:每8192条记录,其实就是一条一级索引,一个索引区间压缩成一个数据块
具体压缩规则:
1、单个批次数据 size < 64KB:如果单个批次数据小于64KB,则继续获取下一批数据后,只至累计到size >= 64KB时,生成下一个压缩数据块。如果平均每条记录小于8byte,多个数据批次压缩成一个数据块
2、单个批次数据 64KB <= size <= 1MB:如果单个批次数据大小在 64KB与1MB之间,则直接生成下一个压缩数据块
3、单个批次数据 size > 1MB:如果单个批次数据直接超过 1MB ,则首先按照 1MB大小截断并生成下一个压缩数据块。剩余数据继续依照上诉规则执行。此时,会出现一个批次数据生成多个压缩数据块的情况。如果平均每条记录的大小超过 128 byte,则会把当前这一个批次的数据压缩成多个数据块。
总结:在一个 xxx.bin字段存储文件中,并不是一个压缩块对应到一条一级索引,而是每8192条数据,构建一条一级索引;
总结:一个column.bin其实就是由一个个压缩的数据块组成的,每个数据块的大小在 64KB ~ 1MB之间。
column.bin数据文件的组成
关于数据标记,数据标记文件也与xxx.bin文件一一对应,是一级索引与数据块之间关系的数据。
每一列字段 xxx.column都对应有一个 xxx.mrk文件标记
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。