点一下关注吧!!!非常感谢!!连续更新!!!
现在已经更新到了:
- Hadoop(已更完)
- HDFS(已更完)
- MapReduce(已更完)
- Hive(已更完)
- Flume(已更完)
- Sqoop(已更完)
- Zookeeper(已更完)
- HBase(已更完)
- Redis (已更完)
- Kafka(已更完)
- Spark(已更完)
- Flink(已更完)
- ClickHouse(正在更新···)
章节内容
上节我们完成了如下的内容:
- 表引擎详解 介绍
- 日志部门
- Log部门
- Memory部门
- Merge部门
MergeTree
ClickHouse中最强盛的表引擎当属 MergeTree(归并树)引擎及该系列(*MergeTree)中的其他引擎。
MergeTree 引擎系列的基本理念如下,当你有巨量数据要插入到表中,你要高效的一批批写入数据片段,并希望这些数据片段在后台按照一定规则归并,相比在插入时不断修改(重写)数据进存储,这种策略会高效很多。
存储结构
创建新表
- CREATE TABLE mt_table(date Date, id UInt8, name String)
- ENGINE = MergeTree PARTITION BY toYYYYMM(date) ORDER BY id;
- CREATE TABLE mt_table3 (
- `date` Date,
- `id` UInt8,
- `name` String
- ) ENGINE = MergeTree PARTITION BY toYYYYMM(date) ORDER BY id;
复制代码 实行的结果如下图所示:
插入数据
- INSERT INTO mt_table VALUES ('2024-07-31', 1, 'wzk');
- INSERT INTO mt_table VALUES ('2024-07-30', 2, 'icu');
- INSERT INTO mt_table VALUES ('2024-07-29', 3, 'wzkicu');
复制代码 实行结果如下图所示:
检察目录
- cd /var/lib/clickhouse/data/default/mt_table
- ls
复制代码 实行结果如下图所示:
我们任意进入一个目录,可以看到:
- bin 是按列生存数据的文件
- mrk 生存块偏移量
- primary.idx 生存主键索引
存储结构
- .
- ├── 202407_1_1_0
- │ ├── checksums.txt
- │ ├── columns.txt
- │ ├── count.txt
- │ ├── data.bin
- │ ├── data.mrk3
- │ ├── default_compression_codec.txt
- │ ├── minmax_date.idx
- │ ├── partition.dat
- │ └── primary.idx
- ├── 202407_2_2_0
- │ ├── checksums.txt
- │ ├── columns.txt
- │ ├── count.txt
- │ ├── data.bin
- │ ├── data.mrk3
- │ ├── default_compression_codec.txt
- │ ├── minmax_date.idx
- │ ├── partition.dat
- │ └── primary.idx
- ├── 202407_3_3_0
- │ ├── checksums.txt
- │ ├── columns.txt
- │ ├── count.txt
- │ ├── data.bin
- │ ├── data.mrk3
- │ ├── default_compression_codec.txt
- │ ├── minmax_date.idx
- │ ├── partition.dat
- │ └── primary.idx
- ├── detached
- └── format_version.txt
复制代码 实行结果如下图所示:
- checknums.txt 二进制校验文件,生存了余下文件的巨细size和size的hash值,用于快速校验文件的完整和精确性
- columns.txt 明文的列信息
- date.bin 压缩格式(默认LZ4)的数据文件,生存了原始数据,以列名 bin 命名。
- date.mrk2 使用了自顺应巨细的索引间隔
- primary.idx 二进制一级索引文件,在建表的时候通过 order by 大概 primary key 声明稀疏索引。
数据分区
数据是以分区目录的情势构造的,每个分区独立分开存储。这种情势,在数据查询的时候,可以有效的跳过无用的数据文件。
分区规则
分区键的取值,生成分区ID,分区根据ID决定,根据分区键的数据范例不同,分区ID的生成现在有四种规则:
- 不指定分键
- 使用整型
- 使用日期范例 toYYYYMM(date)
- 使用其他范例
数据在写入的时候,会按照分区ID落入对应的分区。
分区目录生成
- BlockNum 是一个全局整型,从1开始,每当新创建一个分区目录,此数字就累加1。
- MinBlockNum:最小数据块编号
- MaxBlockNum:最大数据块编号
- 对于一个新的分区,MinBlockNum和MaxBlockNum的值是雷同的
分区目录归并
MergeTree 的分区目录在数据写入过程中被创建,不同的批次写入数据属于同一分区,也会生成不同的目录,在之后某个时刻再归并(写入后10-15分钟),归并后的旧分区目录默认8分钟后删除。
同一个分区的多个目录归并以后得命名规则:
- MinBlockNum:取同一分区中MinBlockNum值最小的
- MaxBlockNum:取同一分区中MaxBlockNum最大的
- Level:取同一分区最大的Level值+1
一级索引
稀疏索引
文件:primary.idx
MergeTree的主键使用PrimaryKey定义,主键定义之后,MergeTree会根据index_granularity间隔(默认8192)为数据生成一级索引并生存至primary.idx中,这种方式就是稀疏索引。
简化情势:通过 ORDER BY 指代 主键
primary.idx 文件的一级索引接纳稀疏索引。
- 稠密索引:每一行索引标记对应一行具体的数据记录
- 稀疏索引:每一行索引标记对应一段数据记录(默认索引粒度是8192)
稀疏索引占用空间小,以是primary.idx内的索引数据常驻内存,取用速度快。
生成规则
primary.idx文件,由于稀疏索引,以是MergeTree要间隔index_granularity行数据才会生成一个索引记录,其他索引值会根据声明的主键字段获取。
查询过程
索引是怎样工作的?对primary.idx文件的查询过程
- MarkRange: 一小段数据区间,按照 index_granularity的间隔粒度,将一段完整的数据划分成多个小的数据段,小的数据段就是MarkRange
- MarkRange与索引编号对应
小案例:
- 200行数据
- index_granularity巨细为5
- 主键ID为int,取值从0开始
共200行数据/5 = 40个MarkRange
假设索引查询 where Id = 3
- 第一步:形成区间格式 [3,3]
- 第二步:进行交集 [3,3] ∩ [0, 199]
以MarkRange的步长大于8分块,进行剪枝:
- 第三步:归并, MarkRange(start0, end20)
在ClickHouse中,MergeTree引擎表的索引列在建表使用ORDER BY语法来指定。
而在官方中,用了下面一副图来说明。
这张图示出了以 CounterID、Date两列为索引列的情况,即先以CounterID为主要关键字排序,再以Date为次要关键字排序,最后用两列的组合作为索引键。Marks与MarkNumbers就是索引标记,且Marks之间的间隔就由建表时的索引粒度参数index_granularity来制定,默认是8192。
在 ClickHouse 之父Alexey Milovidov分享的PPT中,有更加详细的图示:
如许,每一列都通过ORDER BY列进行了索引,查询时,先查找到数据地点的parts,再通过mrk2文件确定bin文件中数据的范围即可。
不过,ClickHouse的稀疏索引与Kafka的稀疏索引不同,可以由用户自由组合多列,因此也要格外注意不要参加太多索引列,防止索引数据过于稀疏,增大存储和查找成本。另外,基数太小(即区分度太低)的列不得当做索引列,因为很有可能横跨多个mark值仍然雷同,没有索引的意义了。
跳数索引
- index_granularity 定义了数据的粒度
- granularity定义了聚合信息汇总的粒度
- granularity定义了一行跳数索引可以或许跳过多少个index_granularity区间的数据
可用范例
- minmax存储指定表达式的极值(如果表达式是tuple,则存储tuple中每个元素的极值),这些信息用于跳过数据块,雷同主键
- set(max_rows)存储指定表达式的唯一值(不超过max_rows个,max_rows=0则表现无穷制)。这些信息可以用于检查 WHERE 表达式是否满足某个数据块
- ngrambf_v1 存储包罗数据块中所有N元短语的布隆过滤器。只可用于字符串上,用于优化equals、like和in表达式的性能。
- tokenbf_v1 跟 ngrambf_v1 雷同,不同于ngrams 存储字符串指定长度的所有片段,它只存储被非字母数据字符分割的片段。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |