ClickHouse(十二):Clickhouse MergeTree系列表引擎 - MergeTree(2)

news2024/11/24 8:40:06

 

进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容!

🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客

📌订阅:拥抱独家专题,你的订阅将点燃我的创作热情!

👍点赞:赞同优秀创作,你的点赞是对我创作最大的认可!

⭐️ 收藏:收藏原创博文,让我们一起打造IT界的荣耀与辉煌!

✏️评论:留下心声墨迹,你的评论将是我努力改进的方向!


目录

1.MergeTree引擎表目录解析

2. MergeTree引擎表设置分区


1.MergeTree引擎表目录解析

下面我们介绍下MergeTree引擎表 t_mt对应到磁盘的数据目录,为了方便从零开始了解,这里我们删除t_mt表,重新创建t_mt表,并插入数据,执行命令如下:

#删除表 t_mt,重新创建表t_mt,并加载数据

node1 :) drop table t_mt;



node1 :)create table t_mt(  id UInt8,  name String,  age UInt8,  birthday Date,  location String ) engine = MergeTree() order by (id,age) partition by toYYYYMM(birthday);



node1 :) insert into t_mt values (1,'张三',18,'2021-06-01','上海'), (2,'李四',19,'2021-02-10','北京'), (3,'王五',12,'2021-06-01','天津'), (1,'马六',10,'2021-06-18','上海'), (5,'田七',22,'2021-02-09','广州');

以上创建好表t_mt,当插入数据完成后,在clickhouse节点/var/lib/clickhouse/data/newdb/路径下会生成对应目录“t_mt”,进入此目录下,可以看到对应的分区目录,如图示:

以上分区目录也可以在系统表“system.parts”中查询得到:

#在系统表 system.part中查询表 t_mt的分区信息:

node1 :) select table ,partition ,name ,active from system.parts where table = 't_mt';

以上表各列的解释如下:

  1. table代表当前表。
  2. partition是当前表的分区名称。
  3. name是对应到磁盘上数据所在的分区目录片段。例如“202102_2_2_0”中“202102”是分区名称,“2”是数据块的最小编号,“2”是数据块的最大编号,“0”代表该块在MergeTree中第几次合并得到。
  4. active代表当前分区片段的状态:1代表激活状态,0代表非激活状态,非激活片段是那些在合并到较大片段之后剩余的源数据片段,损坏的数据片段也表示为非活动状态。非激活片段会在合并后的10分钟左右被删除。

进入到某一个分区目录片段“202102_2_2_0”中,我们可以看到如下目录:

对以上目录的解释如下:

  • checksums.txt:校验文件,使用二进制格式存储。它保存了余下各类文件(primary. idx、count.txt等)的size大小及size的哈希值,用于快速校验文件的完整性和正确性。
  • columns.txt: 存储当前分区所有列信息。使用明文格式存储。
[root@node1 202102_2_2_0]# cat columns.txt

columns format version: 1

5 columns:

`id` UInt8

`name` String

`age` UInt8

`birthday` Date

`location` String
  • count.txt:计数文件,使用明文格式存储。用于记录当前数据分区目录下数据的总行数。
[root@node1 202102_2_2_0]# cat count.txt

2
  • primary.idx:一级索引文件,使用二进制格式存储。用于存放稀疏索引,一张MergeTree表只能声明一次一级索引,即通过ORDER BY或者PRIMARY KEY指定字段。借助稀疏索引,在数据查询的时能够排除主键条件范围之外的数据文件,从而有效减少数据扫描范围,加速查询速度。
  • 列.bin:数据文件,使用压缩格式存储,默认为LZ4压缩格式,用于存储某一列的数据。由于MergeTree采用列式存储,所以每一个列字段都拥有独立的.bin数据文件,并以列字段名称命名。
  • 列.mrk2:列字段标记文件,使用二进制格式存储。标记文件中保存了.bin文件中数据的偏移量信息
  • partition.dat与minmax_[Column].idx:如果指定了分区键,则会额外生成partition.dat与minmax索引文件,它们均使用二进制格式存储。partition.dat用于保存当前分区下分区表达式最终生成的值,即分区字段值;而minmax索引用于记录当前分区下分区字段对应原始数据的最小和最大值。比如当使用birthday字段对应的原始数据为2021-02-17、2021-02-23,分区表达式为PARTITION BY toYYYYMM(birthday),即按月分区。partition.dat中保存的值将会是202102,而minmax索引中保存的值将会是2021-02-17、2021-02-23。

ClickHouse MergeTree引擎表支持分区,索引,修改,并发查询数据,当查询MergeTree表数据时,首先向primary.idx文件中获取对应的索引,根据索引找到【列.mrk2】文件获取对应的数据块偏移量,然后再根据偏移量从【列.bin】文件中读取块数据。

2. MergeTree引擎表设置分区

给表设置分区可以在查询过程中跳过不需要的数据目录,提升查询效率。在ClickHouse中并不是所有的表都支持分区,目前只有MergeTree家族系列的表引擎才支持数据分区。

通过前面的学习,我们知道向MergeTree分区表中每次插入数据时,每次都会生成对应的分区片段,不会立刻合并相同分区的数据,需要等待15分钟左右,ClickHouse会自动合并相同的分区片段,并删除合并之前的源数据片段,当然这里我们也可以手动执行OPTIMIZE 语句手动触发合并分区表中的分区片段。通过下面案例来学习分区表中分区片段合并的规则。

#创建表 login_info ,设置MergeTree引擎

node1 :) create table login_info(

:-]  id UInt8,

:-]  name String,

:-]  log_time Date

:-] ) engine = MergeTree()

:-] order by (id)

:-] partition by toYYYYMM(log_time);



#向表 login_info中插入以下数据

node1 :) insert into login_info values (1,'zs','2021-06-01'),

:-] (2,'ls','2021-06-01'),

:-] (3,'ww','2021-07-01'),

:-] (4,'ml','2021-07-01');



#查看表 login_info 中数据

node1 :) select * from login_info;



SELECT *

FROM login_info

┌─id─┬─name─┬───log_time─┐

│  3  │ ww   │ 2021-07-01 │

│  4  │ ml   │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  1  │ zs   │ 2021-06-01 │

│  2  │ ls   │ 2021-06-01 │

└────┴──────┴────────────┘

4 rows in set. Elapsed: 0.008 sec.

经过以上步骤,在clickhouse节点上查看表login_info数据目录/var/lib/clickhouse/data/newdb/login_info,如下图示:

继续向表 login_info中插入以下数据:

#继续向表login_info中插入以下数据

node1 :) insert into login_info values (5,'zs1','2021-06-01'),

:-] (6,'ls1','2021-06-01'),

:-] (7,'ww1','2021-07-01'),

:-] (8,'ml1','2021-07-01');



#查看表 login_info数据

node1 :) select * from login_info;



SELECT *

FROM login_info

┌─id─┬─name─┬───log_time─┐

│  3  │ ww   │ 2021-07-01 │

│  4  │ ml   │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  1  │ zs   │ 2021-06-01 │

│  2  │ ls   │ 2021-06-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  5  │ zs1  │ 2021-06-01 │

│  6  │ ls1  │ 2021-06-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  7  │ ww1  │ 2021-07-01 │

│  8  │ ml1  │ 2021-07-01 │

└────┴──────┴────────────┘

8 rows in set. Elapsed: 0.006 sec.

通过插入数据之后再次查询发现,相同分区的数据展示在不同的数据块中。在clickhouse节点上再次查看表login_info数据目录/var/lib/clickhouse/data/newdb/login_info,如下图示:

“202106_3_3_0”为例,“202006”为分区,“3”代表数据块的最小编号,“3”代表数据块的最大编号,“0”代表合并的第几次(合并树中块的级别)。

手动执行OPTIMIZE 语句手动触发合并分区表中的分区片段:

#执行如下命令,手动合并分区片段

node1 :) optimize table login_info partition '202106' ;

node1 :) optimize table login_info partition '202107' ;



#查看表 login_info中的数据:

node1 :) select * from login_info;



SELECT *

FROM login_info

┌─id─┬─name─┬───log_time─┐

│  3  │ ww   │ 2021-07-01 │

│  4  │ ml   │ 2021-07-01 │

│  7  │ ww1  │ 2021-07-01 │

│  8  │ ml1  │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  1  │ zs   │ 2021-06-01 │

│  2  │ ls   │ 2021-06-01 │

│  5  │ zs1  │ 2021-06-01 │

│  6  │ ls1  │ 2021-06-01 │

└────┴──────┴────────────┘

8 rows in set. Elapsed: 0.006 sec.

通过合并分区片段之后,在clickhouse节点上再次查看表login_info数据目录/var/lib/clickhouse/data/newdb/login_info,如下图示:

经过一段时间再次查询当前目录数据,只剩余合并最后的两个分区片段,如下图所示:

MergeTree分区表合并分区规则如下:获取相同分区片段中最小编号和最大编号,组合成新的分区片段,同时修改合并的次数(合并树中块的级别),合并示意图如下:

继续向表login_info中插入数据:

#继续向表login_info中插入以下数据

node1 :) insert into login_info values (9,'zs1','2021-06-01'),

:-] (10,'ls1','2021-06-01'),

:-] (11,'ww1','2021-07-01'),

:-] (12,'ml1','2021-07-01');



#查看表 login_info数据

node1 :) select * from login_info;

SELECT *

FROM login_info

┌─id─┬─name─┬───log_time─┐

│  3 │ ww   │ 2021-07-01 │

│  4 │ ml   │ 2021-07-01 │

│  7 │ ww1  │ 2021-07-01 │

│  8 │ ml1  │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│ 11 │ ww1  │ 2021-07-01 │

│ 12 │ ml1  │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  1 │ zs   │ 2021-06-01 │

│  2 │ ls   │ 2021-06-01 │

│  5 │ zs1  │ 2021-06-01 │

│  6 │ ls1  │ 2021-06-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  9 │ zs1  │ 2021-06-01 │

│ 10 │ ls1  │ 2021-06-01 │

└────┴──────┴────────────┘

12 rows in set. Elapsed: 0.006 sec

在clickhouse节点上再次查看表login_info数据目录/var/lib/clickhouse/data/newdb/login_info,如下图示:

再次执行合并分区命令,合并表login_info分区片段:

#执行如下命令,手动合并分区片段

node1 :) optimize table login_info partition '202106' ;

node1 :) optimize table login_info partition '202107' ;



#查看表 login_info中的数据:

node1 :) select * from login_info;

SELECT *

FROM login_info

┌─id─┬─name─┬───log_time─┐

│  3  │ ww   │ 2021-07-01 │

│  4  │ ml   │ 2021-07-01 │

│  7  │ ww1  │ 2021-07-01 │

│  8  │ ml1  │ 2021-07-01 │

│ 11  │ ww1  │ 2021-07-01 │

│ 12  │ ml1  │ 2021-07-01 │

└────┴──────┴────────────┘

┌─id─┬─name─┬───log_time─┐

│  1  │ zs   │ 2021-06-01 │

│  2  │ ls   │ 2021-06-01 │

│  5  │ zs1  │ 2021-06-01 │

│  6  │ ls1  │ 2021-06-01 │

│  9  │ zs1  │ 2021-06-01 │

│ 10  │ ls1  │ 2021-06-01 │

└────┴──────┴────────────┘

12 rows in set. Elapsed: 0.008 sec.

通过合并分区片段之后,在clickhouse节点上再次查看表login_info数据目录/var/lib/clickhouse/data/newdb/login_info,如下图示:

经过一段时间再次查询当前目录数据,只剩余合并最后的两个分区片段,如下图所示:

此外,表设置分区字段时,分区健不仅可以指定成时间列,也可以是表中任意列或者列的表达式。下面案例使用表中的地区列当做分区:

#创建表 emp_info ,使用MergeTree分区

node1 :) create table emp_info (

:-] id UInt8,

:-] name String,

:-] age UInt8,

:-] loc String,

:-] salary Decimal32(2)  

:-] )engine = MergeTree()

:-] order by id

:-] partition by loc;



# 向表中插入以下数据

node1 :) insert into emp_info values (1,'张三',18,'上海',10.11),

:-] (2,'李四',19,'北京',100.123),

:-] (3,'王五',20,'上海',200.2),

:-] (4,'马六',21,'上海',300.456),

:-] (5,'田七',22,'北京',400.78),

:-] ;



#查看表中的数据,可以观察到所有数据都是按照地区合并在一起。

node1 :) select * from emp_info;



SELECT *

FROM emp_info

┌─id─┬─name─┬─age─┬─loc──┬─salary─┐

│  2   │ 李四    │  19   │ 北京     │ 100.12   │

│  5   │ 田七    │  22   │ 北京     │ 400.78   │

└───┴────┴────┴─────┴──────┘

┌─id─┬─name─┬─age─┬─loc──┬─salary─┐

│  1   │ 张三    │  18   │ 上海     │  10.11   │

│  3   │ 王五    │  20   │ 上海     │ 200.20   │

│  4   │ 马六    │  21   │ 上海     │ 300.45   │

└───┴────┴────┴─────┴──────┘

5 rows in set. Elapsed: 0.006 sec.

注意:如果按照字符串字段来进行分区,在底层/var/lib/clickhouse/data/newdb/目录下对应的表emp_info中的分区片段名称是使用字符串的hashcode+编码的形式来命名。


👨‍💻如需博文中的资料请私信博主。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/839744.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT 使用单例模式

目录 1. 单例模式介绍 2.单例模式实现 1. 单例模式介绍 有些时候我们在做 qt 项目的时候,要用到很多类. 例如我们用到的类有 A,B,C,D. 其中,A 是 B,C,D 中都需要用到的类,A 类非常的抢手. 但是,A 类非常的占内存,定义一个 A 对象需要 500M 内存,假如在 B,C,D 中都定义一个 A 类…

解决github打不开的方法

解决github打不开的方法 本文参考文章:解决可ping通但无法访问github网站的问题 一、确定域名github.com的ip地址 进入网址 IP/服务器github.com的信息 - 站长工具 (chinaz.com),查看 ip 地址。 20.205.243.166 github.com二、确定域名github.global.…

【websocket - Tornado】简易聊天应用

1、背景 项目测试的过程中需要自己搭建一个webscoket站点,确保此类服务接入后台系统后访问不受影响。python的服务框架常用的有Flask、Django、Tornado,每个框架的侧重点不同,导致使用的场景就会有所差异。 Flask轻量级,采用常规的同步编程方式,需要安装其他模块辅助,主…

JavaEE——网络初识 (简单介绍两种协议以及网络通信的基础概念)

文章目录 一、简单了解网络发展二、网络通信基础认识三、利用UDP举例解释网络信息传输 一、简单了解网络发展 总的来讲,网络的发展史就是,先是一小部分的计算机之间连接通信,随着技术发展,逐渐扩大范围,形成了我们当前…

【Yolov5+Deepsort】训练自己的数据集(1)| 目标检测追踪 | 轨迹绘制

📢前言:本篇是关于如何使用YoloV5Deepsort训练自己的数据集,从而实现目标检测与目标追踪,并绘制出物体的运动轨迹。本章讲解的为第一个内容:简单介绍YoloV5Deepsort中所用到的目标检测,追踪及sort&Depp…

diffusion model2 扩散模型的文本信息融合、交叉注意力机制、lora

前言 在上一篇文章中,我们剖析了diffusion model的原理,而在这一篇文章中,我们探讨与扩散模型有关的其他话题,包括扩散模型的unet是如何在推理噪声的过程中,融入文本信息的考量?其原理为交叉注意力机制&am…

Kubernetes 整体架构介绍

架构图 Kubernetes 主要由以下几个核心组件组成: etcd 保存了整个集群的状态;kube-apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;kube-controller-manager 负责维护集群的状态&#xf…

【LeetCode】287. 寻找重复数

287 . 寻找重复数(中等) 方法 快慢指针 思路 要解决这道题首先要理解如何将输入的数组看作为链表。对于数组 nums 中的数字范围在 [1, n],考虑两种情况: 如果数组中没有重复的数字,以 [1, 3, 4, 2] 为例,将…

从8个新 NFT AMM,聊聊能如何为 NFT 提供流动性

DeFi 的出现,开启了数字金融民主化的革命。其中,通过 AMM 自由创建流动性池极大地增加了 ERC-20 Token 的流动性,并为一些长尾 Token 解锁了价值的发现,因而今天在链上可以看到各种丰富的交易、借贷和杠杆等活动。 而另一方面&am…

uni-app——下拉框多选

一、组件components/my-selectCheckbox.vue <template><view class"uni-stat__select"><span v-if"label" class"uni-label-text">{{label &#xff1a;}}</span><view class"uni-stat-box" :class"…

SpringBoot实现数据库读写分离

SpringBoot实现数据库读写分离 参考博客https://blog.csdn.net/qq_31708899/article/details/121577253 实现原理&#xff1a;翻看AbstractRoutingDataSource源码我们可以看到其中的targetDataSource可以维护一组目标数据源(采用map数据结构)&#xff0c;并且做了路由key与目标…

《华为认证》SR-MPLS-TE

实验需求&#xff1a;运营商网络配置SR-MPLS-TE&#xff0c;实现CE1和CE2之间的互访流量通过PE1-P2-P4-PE3。 步骤1&#xff1a;配置运营商网络的IGP协议&#xff08;本实验采用ISIS协议&#xff09; PE1&#xff1a; isis 1is-level level-2cost-style widenetwork-entity 49…

一个.NET开发的Web版Redis管理工具

今天给大家推荐一款web 版的Redis可视化工具WebRedisManager&#xff0c;即可以作为单机的web 版的Redis可视化工具来使用&#xff0c;也可以挂在服务器上多人管理使用的web 版的Redis可视化工具。 WebRedisManager基于SAEA.Socket通信框架中的SAEA.RedisSocket、SAEA.WebApi两…

Python实现决策树算法:完整源码逐行解析

决策树是一种常用的机器学习算法&#xff0c;它可以用来解决分类和回归问题。决策树的优点是易于理解和解释&#xff0c;可以处理数值和类别数据&#xff0c;可以处理缺失值和异常值&#xff0c;可以进行特征选择和剪枝等操作。决策树的缺点是容易过拟合&#xff0c;对噪声和不…

云原生应用里的服务发现

服务定义&#xff1a; 服务定义是声明给定服务如何被消费者/客户端使用的方式。在建立服务之间的同步通信通道之前&#xff0c;它会与消费者共享。 同步通信中的服务定义&#xff1a; 微服务可以将其服务定义发布到服务注册表&#xff08;或由微服务所有者手动发布&#xff09;…

内网穿透:ngrok使用教程

一、前言 平时我们在本地8080端口创建一个服务的时候&#xff0c;都是使用localhost:8080访问我们的web服务。但是外网是不能访问我们的web服务的。这时&#xff0c;如果你要实现外网访问的功能就需要实现内网穿透&#xff0c;ngrok就是可以帮我们实现这个功能。 二、ngrok介…

岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测 多通道振弦传感器信号转换器VTI104_DIN 是轨道安装式振弦传感器信号转换器&#xff0c;可将振弦、温度传感器信号转换为 RS485 数字信号和模拟信号输出&#xff0c;方便的接入已有监测系统。 传感器状态 专用指示灯方…

unraid docker桥接模式打不开页面,主机模式正常

unraid 80x86版filebrowser&#xff0c;一次掉电后&#xff0c;重启出现权限问题&#xff0c;而且filebrowser的核显驱动不支持amd的VA-API 因为用不上核显驱动&#xff0c;解压缩功能也用不上&#xff0c;官方版本的filebrowser还小巧一些&#xff0c;18m左右 安装的时候总是…

QTableWidget对单元格(QWidget/QTableWidgetItem)的内存管理[clearContents()]

目录 现象结论代码验证clearContents() 会释放QTableWidgetItem 和QWidget 对象&#xff0c;但是不指向nullptrmemorytable.hmemorytable.cpp断点情况 验证clearContents()是延时释放QWidget 的而QTableWidgetItem 立即释放 现象 结论 clearContents() 会清除表格中的所有单元格…

小程序 view下拉滑动导致scrollview滑动事件失效

小程序页面需要滑动功能 下拉时滑动&#xff0c;展示整个会员卡内容&#xff0c; 下拉view里包含了最近播放&#xff1a;有scrollview&#xff0c;加了下拉功能后&#xff0c;scrollview滑动失败了。 <view class"cover-section" catchtouchstart"handletou…