clickHouse MergeTree核心原理

2023-10-30

1、MergeTree的创建方式与存储结构

1.1 MergeTree的创建方式

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
    ...
    INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
) ENGINE = MergeTree()
-- 排序键【必填】 默认情况下主键与排序键相同,可以是单个列,也可以通过元组声明多个列
ORDER BY expr
-- 分区键【选填】 可以时单个列,也可以通过元组声明多个列字段,同事也支持列表达式;如果不声明则会生成名为all的分区
[PARTITION BY expr]
-- 主键【选填】 会按照主键字段生成一级索引,默认情况下通常只需要声明排序键代为指定主键,MergeTree允许主键重复【ReplacingMergeTree可以去重】
[PRIMARY KEY expr]
-- 【选填】 声明数据按照何种方式进行抽样,如果声明了则主键中也需要声明同样的表达式
[SAMPLE BY expr]
[TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
-- index_granularity=8192 表示索引的粒度,表示每隔8192行生成一条索引
-- index_granularity_bytes=10*1024*1024 表示根据一批次写入数据量大小,自适应索引生成间隔大小,这里表示每写入10M就生成一个索引
-- enable_mixed_granularity_parts 表示是否开启自适应索引间隔功能,默认开启
-- merge_with_ttl_timeout 数据ttl功能
-- storage_policy 多路径存储策略
[SETTINGS name=value, ...]

1.2 MergeTree的存储结构

table_name
   |
   |----partition_1  //分区目录余下的各类数据文件都是以分区形式存放的,属于相同分区的数据,最终会被合并到同一个分区目录
   |        |
   |        |-------checksums.txt  //校验文件,二进制存储。保存了余下各类文件的size大小和size的哈希值,校验文件的完整性和正确性
   |        |
   |        |-------columns.txt  //列文件信息,明文存储,保存分区下的列字段信息
   |        |
   |        |-------count.txt  //记录当前分区瞎的数据的总行数
   |        |
   |        |-------primary.idx  //一级索引文件,二进制存储,在数据查询的时候能排除主键条件范围之外的数据文件。
   |        |
   |        |-------[Column].bin  //数据文件,压缩格式存储,默认为LZ4压缩格式。MergeTree采用列式存储,所以每一个文件都有一个.bin数据文件。
   |        |
   |        |-------[Column].mrk  //列字段标记文件,二进制存储,标记文件中保存了.bin文件中的偏移信息。标记文件与稀疏索引文件一一对应,查询时先通过稀疏索引文件找到对应的数据偏移信息(.mrk),再通过偏移量直接从.bin文件中读取数。
   |        |
   |        |-------[Column].mrk2  //当使用了自适应大小的索引间隔,则标记文件会以.mrk2命名。工作原理与.mrk文件相同
   |        |
   |        |-------partition.dat  //如果使用了分区键,则会额外生成partition.dat与minmax索引文件,均使用二进制格式文件。保存当前分区下分区表达式最终生成的值。
   |        |
   |        |-------minmax_[Column].idx  //minmax索引记录当前分区下分区字段对应的原始字段的最大和最小值
   |        |
   |        |-------skip_idx_[Column].idx  //如果在表中声明了耳机索引,则会额外生成耳机索引与标记文件,使用二进制存储
   |        |
   |        |-------skip_idx_[Column].mrk
   |        
   |----partition_2
   |
   |----partition_2

1.3 数据分区

数据分区:针对本地数据而言,对数据的纵向切分

数据分片:针对所有分片上的数据而言,是对数据的横向切分

1.3.1数据分区规则

  • 不指定分区键,则分区默认为all,所有的数据都会写进这个分区。
  • 整形,则分区ID的取值为指定的整形的值
  • 日期类型或者能转换为YYYYMMDD格式的整形,则直接按照整形的字符串数据,作为分区ID的取值
  • 其他类型:当为String Float类型,则通过128位hash值作为分区ID的取值
  • 当分区键为元组的多个列时,分区ID按照上面的方式生成,多个分区ID之间通过“-”符号拼接。

1.3.2分区目录的命名规则

比如分区ID:202103_1_1_0   => {PartitionID}_{MinBlockNum}_{MaxBlockNum}_{Level}

PartitionID: 分区ID,用户创建表时指定的。

MinBlockNum:最小的数据块编号,这是一个整形的全局的自增长编号,当每创建一个分区目录时,计数就累加1。

MaxBlockNum:最大的数据块编号。和MinBlockNum一样当分区创建的时候,MinBlockNum=MaxBlockNum的值

Level:合并的层级,某个分区被合并过的次数,不是全局累加的,对每一个创建的分区,其初始值均为0。之后,以分区为单位,如果相同的分区发生合并动作,则在相应的分区内计数累加1

1.3.3分区目录合并过程

MergeTree会随着每一批次数据写入(一次insert语句)会成成一批新的分区目录,目录状态是激活(active=1)。即便不同批次写入的数据属于相同分区,也会生成不同的分区目录。所以对于同一个分区而言会存在多个分区目录的情况。在写入之后的10~15分钟(默认是)会通过后台任务将数据同一分区的多个数据目录合并成一个目录。已经存在的旧分区目录不会立即删除,目录状态是未激活(active=0),会在之后的8分钟(默认是)通过后台任务被删除。

合并的时候MinBlockNum、MaxBlockNumLevel的值变更

MinBlockNum:取同一分区中所有的目录中最小的MinBlockNum的值

MaxBlockNum:取同一分区中所有的目录中最大的MaxBlockNum的值

Level:取同一分区内所有目录中最大的Level值加1

2、一级索引

MergeTree的主键定义之后,MergeTree会依据index_grabularity间隔(默认8192行),为数据生成一级索引并保存至primary.idx文件中,索引数据按照Primary Key排序。当用Order By来指定主键的时候索引和数据文件会按照完全相同的排序规则。

2.1稀疏索引

  • 稀疏索引:每一行索引标记对应的是一段数据。Clickhouse使用的就是稀疏索引,由于稀疏索引占用的空间少,所以primary.idx内的索引数据常驻内存,取用速度非常快。
  • 稠密索引:每一行索引标记都会对应到一行具体的数据记录

2.2索引粒度

 

2.3索引数据的生成规则

由于是稀疏索引,所以MergeTree需要间隔index_grabularity间隔行数据才会生成一条索引记录,其索引值会依据声明的主键字段获取。会每间隔8192行取一次主键id值作为索引值,最终会被写入primary.idx文件进行保存。索引如果主键是元组类型的多个列,则隔8192行取所有的主键列的值作为索引值,索引值按照主键字段顺序紧密排列在一起。

2.4索引的查询过程

MarkRange在ClickHouse中是用于定义标记区间的对象。一个具体的数据段即是一个MarkRange。MarkRange与索引编号对应,使用start和end两个属性表示其区间范围。

索引查询过程:

(1)生成查询条件的区间:首先将查询条件转换为条件区间。即便是单个值的查询条件,也会被转换成区间的形式。

Where ID = ‘A003’ => [‘A003’, ‘A003’]
Where ID > ‘A000’ => [‘A000’, +inf]
Where ID < ‘A188’ => [‘-inf’, ‘A188’]
Where ID like ‘A006%’ => [‘A006’, ‘A007’]

(2) 递归交集判断:以递归的形式,依次对MarkRange的数值区间与条件区间做交际判断。从最大的区间[A000, +inf]开始:

  • (2.1)如果不存在交集,则直接通过剪枝算法优化此段MarkRange。

  • (2.2)如果不存在交集,且MarkRange的步长大于8(end-start),,则将此区间进一步拆分成8个子区间(由merge_tree_coarse_index_granularity指定,默认值为8),并重复此规则,继续做递归交集判断。

  • (2.3)如果存在交集,且MarkRange不可再分解(步长小于8),则记录MarkRange则返回。

(3)合并MarkRange区间:将最终匹配的MrakRange聚在一起,合并他们的范围。

3、二级索引

二级索引又称为跳数索引,由数据的聚合信息构建而成。条数索引默认关闭,需要在使用的时候开启。条数索引需要在Create语句内定义,它支持使用元组和表达式的形式声明:

Index index_name expr type index_type(…) GRANULARITY granularity

如果声明了条数索引则会额外生成索引与标记文件(skp_idx_[column].idx与skp_idx_[column].mrk)。

granularity和index_granularity区别是:index_granularity定义了数据的粒度,granularity定义了一行条数索引能够跳过多少个index_granularity区间的数据。

当index_granularity=8192, granularity=3时,数据会按照index_granularity划分为n等分,则二级索引会跨越3个index_granularity区间,取第一个索引列的最小值,以及取第三个区间索引列的最大值,来生成一条索引。

跳数索引的类型:minmax,set,ngrambf_v1和tokenbf_v1。

4、数据存储

4.1各列独立存储

MergeTree中数据按列存储,每列都有一个与之对应的.bin数据文件,数据文件以分区目录形式存放,所以在.bin文件中只会保存当前分区片段内的这一部分数据。

首先数据时压缩的,目前支持LZ4、ZSTD、Multiple和Delta算法等,其次数据会按照ORDER BY的声明排序:最后数据是以压缩数据块的形式写入到.bin文件中的。

4.2压缩数据块

.bin文件是由多个压缩数据块组成,每个压缩数据块的体积,按照其压缩前的字节大小,都被严格控制在64KB~1MB。

其上下限分别由min_compress_block_size(默认65536)与max_compress_block_size(默认1048576)。

MergeTree在数据具体写入过程中,会按照索引粒度(默认情况下每次取8192行)按批次获取数据并进行处理:

  1. 单个批次数据size<64kb:如果单个批次数据小于64kb,则继续获取下一批次数据,直至累积到size>=64kb,生成下一个数据块。
  2. 单个批次64kn<=size<=1MB:如果单个批次数据大小恰好在64kb与1MB之间则直接生成下一个压缩数据块。
  3. 单个批次数据size > 1md:如果单个批次数据直接超过1md,则首先按照1md大小阶段并生成数据块,剩余的执行上述流程。

5、数据标记

5.1 数据标记生成规则

数据标记文件与.bin文件一一对应。每一个列字段[Column].bin文件都有一个与之对应的[Column].mrk数据标记文件,用于记录数据在.bin文件中的偏移量信息。

一行标记数据使用一个元组表示,元组内包含两个整形数值的偏移量信息:(压缩文件中的偏移量,解压缩块中的偏移量)

 

标记数据文件数据示意图

每一行标记数据都表示了一个片段的数据(默认8192行)在.bin压缩文件中的读取位置信息。标记数据不常驻内存,使用LRU缓存策略加快其取用速度。

5.2数据标记工作方式

6、写入和查询的执行过程

6.1写入过程

1、数据写入首先生成分区目录,每一次执行一次写入的INSERT语句都会生成一个新的分区目录(所以每次写的时候别写太少的数据)。在后续的某一个时刻,后台任务会将属于相同分区的目录按照规则合并在一起。

2、按照index_granularity索引粒度,会分别生成primary.idx以及索引(如果声明了二级索引,还会生成二级索引文件)、每一列字段的.mrk数据标记和.bin压缩数据文件

6.2查询过程

如果一条查询语句没有指定任何where条件,或是置顶哦了where条件,但条件没有匹配到任何索引(分区索引、一级索引、二级索引),那么MergeTree就不能预先减小数据范围。后续查询的时候会扫描所有的分区,一级目录内索引段的最大区间,在这种情况下MergeTree依然能借助数据标记,以多线程的方式同时读取多个压缩数据块,以提升性能。

 

6.3数据标记与压缩数据块的对应关系

6.3.1多对一

这种情况是:当一个数据间隔内的数据未压缩大小Size小于64KB,由于会继续读取下一个间隔的数据凑成最小的64KB进行压缩,所以会生成多个数据标记对应一个压缩块中的多个数据间隔。

6.3.2一对一

这种情况是:一个数据间隔内的数据未压缩大小在64KB<SIZE<1MB之内,所以刚好能凑成一个压缩块。

6.3.3一对多

这种情况是:一个间隔内的数据未压缩大小SIZE>1MB

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

clickHouse MergeTree核心原理 的相关文章

  • 搭建spring-cloud-alibaba微服务项目:springBoot服务+nacos注册中心+nacos配置中心+feign服务交互+gateway网关

    项目说明 从0 1 搭建cloud alibaba微服务项目 包括各个springBoot服务 nacos注册中心 nacos配置中心 feign服务交互 gateway网关 首先统一微服务种alibaba相关组件的依赖版本问题 官方参考文
  • Android中LocalSocket使用

    http www cnblogs com bastard archive 2012 10 09 2717052 html 一 Socket Socket最初用在基于TCP IP网络间进程通信中 以客户端 服务器模式进行通信 实现异步操作 共
  • vue项目实现微信扫码登录

    要在Vue项目中实现微信扫码登录功能 你可以按照以下步骤进行操作 注册微信开放平台账号并创建应用 首先 在微信开放平台上注册一个账号 并创建一个应用 获取到应用的AppID和AppSecret 安装 Axios 在Vue项目中使用Axios
  • python setup.py install报错“error: can‘t create or remove files in install directory”

    运行python setup py install 报错 running install error can t create or remove files in install directory The following error
  • 叶面积指数(LAI)介绍以及遥感估算方法

    前言 叶面积指数精度是正确预测产量的重要参数之一 同时 还有那么多疑问 如何才能正确 以及如何使用最有效的方法计算叶面积指数 LAI 什么是最佳 LAI 哪些估算叶面积指数精度的方法比较好 本文为初学者做了简要介绍 并在文章末尾附了两种估算
  • 史上最全的正则表达式-匹配中英文、字母和数字

    1 匹配中文 u4e00 u9fa5 2 英文字母 a zA Z 3 数字 0 9 4 匹配中文 英文字母和数字及下划线 u4e00 u9fa5 a zA Z0 9 同时判断输入长度 u4e00 u9fa5 a zA Z0 9 4 10 5
  • vue3中将数据导出为excel表格

    目标 将vue3接口中得到的数据转换为数组 然后利用Export2Excel导出为excel表 1 开始之前要准备 1 Export2Excel js文件 在后面标题4附上 我是放在until目录下 2 npm i xlsx 安装失败后面加
  • 6.4-为何要深度学习

    文章目录 一 模型对比 二 模块化 Modularization 三 语音辨识 3 1 类比 Analogy 3 2 端到端学习 End to end Learning 四 复杂任务 五 更多的原因 一 模型对比 在参数量相同的条件下 究竟
  • dede仿站时----实现简单图片滚动(轮流图)效果

    第一次发文章 说的不好 请见谅 刚处理了标题这个问题 也百度半天没好办法 自己混乱的整理出来 所以发出来 说说自己的解决办法 直接代码 图 代码 dede arclist typeid 20 orderby pubdate type ima
  • 实战 逆向最新黄鸟抓包软件

    前言 观众器者为良匠 观众病者为良医 这篇文章分析了知名抓包软件HttpCanary高级功能的使用限制 使用了许多实用的工具 过程写的尽可能的详细 希望对大家有所帮助 笔者实践环境 pixel 6 Android 12 frida 15 1
  • 通过CUDA deviceQuery分析NVIDIA显卡性能

    参考 http blog sina com cn s blog 471e6c930102wlp5 html 序号 名称 值 解释 1 Detected 1 CUDA Capable device s 1 检测到1个可用的NVIDIA显卡设备
  • JetBrains全家桶激活地址

    全家桶地址 https www jetbrains com products html fromMenu JetBrains 授权服务器 License Server URL http idea imsxm com 使用方法 激活时选择Li
  • Oracle中RMAN基本命令教程

    一 target 连接数据库 1 本地 oracle oracle rman target 2 远程 oracle oracle rman target sys oracle orcl 二 show 查看配置 RMAN gt show al
  • JSP之cookie的使用说明

    1 cookie介绍 1 来自于Servlet规范中提供一个工具类 2 如果两个Servlet为同一个用户 用一个浏览器提供服务 此时借助于用户的cookie实现数据共享 3 cookie在现实生活中相当于用户的会员卡 当没有手动清除浏览器
  • Linux 进程间通讯

    文章目录 一 进程间通讯概念 进程通讯介绍 进程间通讯的分类 二 进程间通讯之管道 1 无名管道 无名管道概述 无名管道 API 无名管道的实例 无名管道的读写特点 设置为非阻塞的方法 2 有名管道 有名管道的概述 有名管道的使用 有名管道
  • RISC-V --rocket-chip generator介绍及其仿真使用

    最近工作使用 rocket chip generator 仿真非极大值抑制算法 C语言编写 分析其时序模型和riscv汇编指令 这里将rocket chip generator的使用方法总结一下 说明 使用的rocket chip gene
  • MOSFET知识小结

    MOSFET知识小结 MOSFET的基础知识 参见百度百科 场效应管 MOSFET的驱动 专用IC驱动 优点 电路集成度高 驱动能力强 使用简单 缺点 成本高 适用范围 非典型应用 如NMOS的高边驱动 驱动电流要求高的情况 注意事项 使用
  • 恒林家居引入纷享销客CRM系统,领跑家居行业营销数字化进程

    近日 恒林家居股份有限公司 股票代码 603661以下简称为 恒林家居 携手纷享销客在湖州召开了CRM项目启动会 双方领导及核心项目人员齐聚一堂 展开了深度交流并达成了重要共识 作为家居行业的领军企业 恒林家居自22年扩容 大家居 战略赛道
  • apache2.4配置服务器,文件都是从配好的服务器上直接拿下来的,极具参考性

    hello 大家好 我是咖啡汪 今天刚好给服务器配置了 SSL 证书 所以写这篇文章来分享下心得 以下文件包括了80 端口监听代理映射 和 443 端口监听代理映射 1 下载下来的ssl 证书截图如下 2 修改 httpd conf 内容如
  • java入门一:java语法基础

    1 注释 标识符 单行注释 多行注释 文字 文档注释 文字 注释不会被编译 写给程序员看 平时写代码一定写注释 方便别人看的懂你的代码 或者写久了自己忘了干嘛的 关键字 abstract assert boolean int class 不

随机推荐

  • 毕业差不多一年,跳槽华为od岗,已入职

    先说一下2022年上半年od岗的面试流程 简历筛选 全日制本科以上 机试 性格面试 技术一面 技术二面 hr面 主管面 博主当时面试到入职用了两个多月 都是线上面试 可以约晚上或者周末 机试 三道算法题 大概就是力扣简单 中等 困难的三种类
  • python中while循环打印99乘法表

    花式打印9 9乘法表 第一个计数器 i 1 while i lt 10 第二个计数器 j 1 while j lt i print d d d t j i i j end j 1 换行 print i 1 输出换行 print i 1 wh
  • 行业代码小程序开发制作方案

    随着移动互联网的快速发展 小程序成为用户获取服务的新途径 尤其在行业领域 如餐饮 零售 教育等 小程序的应用越来越广泛 方案旨在开发一款行业代码小程序 为行业用户提供便捷 高效的服务体验 一 产品定位 产品定位为行业代码小程序 旨在为行业用
  • 数据库基本概念review

    1 基本概念 1 1 数据库阶段 人工管理阶段 文件系统阶段 使用文件系统来进行管理 缺陷 数据荣誉 数据不一致 数据库阶段 三大事件 层次模型的出现 网状模型的出现 关系模型的出现 Codd 1 2 DB DBMS DBS定义 数据库 D
  • Zip压缩解压缩之C++实现。

    压缩 可压缩单一文件 也可压缩文件夹里的多个文件 包括文件夹里面的子文件夹 压缩的目标文件格式无限制 demo文件使用的是 text h cpp png bmp wav mp4等 解压缩 非覆盖解压缩 1 codeproject下载地址 h
  • openssl rand 密码字符长度 -base64

    openssl rand 6 base64 MuCB2GeN openssl rand 14 base64 xIHqPvf9PCkRr355gyg OpenSSL简介 在所有的类 Unix 发行版 Solaris Mac OS X 和 Wi
  • qt之QSqlQuery类执行SQL语句

    转载自 https wizardforcel gitbooks io qt beginning content 28 html 导语 SQL即结构化查询语言 是关系数据库的标准语言 前面两节中已经在Qt里利用QSqlQuery类执行了SQL
  • AngularJS 发送POST请求到后台

    这两个周公司要换前端框架 采用Ionic AngularJS来展示App 原来的App采用的是H5做的 说是H5用户体验不怎么好 所以叫我调研下 说真的 刚开始真的是一脸懵逼 找各种资料 论坛 视频 看了很多博客 很多大牛都说学习Ionic
  • 决策树算法的核心思想

    本文来自 公众号 自然语言处理与机器学习 作者 忆臻 一 算法思想 决策树 decision tree 是一个树结构 可以是二叉树或非二叉树 其每个非叶节点表示一个特征属性上的测试 每个分支代表这个特征属性在某个值域上的输出 而每个叶节点存
  • Prompt工程师指南[应用篇]:Prompt应用、ChatGPT

    1 ChatGPT Prompt Engineering 主题 与 ChatGPT 对话 Python 笔记本 ChatGPT介绍 ChatGPT是OpenAI训练的一种新型模型 可以进行对话交互 该模型经过训练 可以按照提示中的指令 在对
  • 获取顺序栈的栈顶元素

    转至 http www nowamagic net librarys veda detail 2276 获取顺序栈的栈顶元素 GetTop S e 若栈存在且非空 用e返回S的栈顶元素 参考之前线性表的话 就是设一个存储栈顶的变量 e 然后
  • 18、INSERT:插入数据(添加数据)

    数据库与表创建成功以后 需要向数据库的表中插入数据 在 MySQL 中可以使用 INSERT 语句向数据库已有的表中插入一行或者多行元组数据 基本语法 INSERT 语句有两种语法形式 分别是 INSERT VALUES 语句和 INSER
  • 实现打怪得分效果。(Unity)

    首先创建一个Text文本UI组件 并且通过锚点进行文本位置的摆放 并通过修改下面箭头处的值调整Text文本的大小和颜色 如果有字体也可以修改字体样式 也可以在添加组件处添加一个shadow组件修改x和y的值 使文本具有立体和阴影感看起来更有
  • STM32——蓝牙模块HC06

    STM32 蓝牙模块HC06 选用的芯片是STM32F407的芯片 一个HC06的蓝牙模块 我们采用串口连接 所以我们在芯片原理图找出串口模块 参数 STM32串口异步通信定义的参数传送格式 起始位 数据位 8位或者9位 奇偶校验位 第9位
  • 第二章 计算机发展与应用

    计算机从诞生至今已经经历了多个阶段的发展 包括 1 电子管时代 1940年代 1950年代 计算机使用电子管作为主要的电子元件 这些计算机体积庞大 功耗大 但是它们标志着计算机的诞生 并且在二战期间被广泛应用于军事领域 2 晶体管时代 19
  • 6.2、客户/服务器方式(C/S)&对等方式(P2P方式)

    网络应用程序运行在处于网络边缘的不同的端系统上 通过彼此间的通信来共同完成某项任务 开发一种新的网络应用首先要考虑的问题就是 网络应用程序在各种端系统上的组织方式和它们之间的关系 color red 网络应用程序在各种端系统上的组织方式和它
  • TypeScript与Date类型

    js的继承方式 经典的js寄生组合式继承 function MyDate Date apply this arguments this abc 1 function inherits subClass superClass function
  • mysql5.7.17安装+mysql error:1524+1045+外部访问出错

    1 mysql5 7 17安装 windows10系统 下载mysql 5 7 17 winx64 copymysql 5 6 35 winx64的data文件 进入安装数据库目录bin cd C ProgramFiles mysql 5
  • 指数历年各月涨幅分析-验证五穷六绝七翻身是否可信

    指数通常反映了一个行业或者一类股票的行情数据 本文将对697支指数的历史各月涨幅进行分析 为量化投资作一个参考 从分析中 我们可以验证五穷六绝七翻身是否可信 并找出上涨概率最大的一些指数和月份 1 数据准备 本文程序中用到两个数据 1 in
  • clickHouse MergeTree核心原理

    1 MergeTree的创建方式与存储结构 1 1 MergeTree的创建方式 CREATE TABLE IF NOT EXISTS db table name ON CLUSTER cluster name1 type1 DEFAULT