ClickHouse|MergeTree引擎之数据分区
前言
前面通过 一文了解ClickHouse 介绍过ClickHouse,特性,结构,使用场景。自己并未完全深入学习clickhouse,因为公司打算小范围使用ClickHouse,所以有必要深入学习之。本文了解 Clickhouse 的分区感念 和 分区合并规则。
MergeTree数据分区规则
创建按照月份为分区条件的表 tab_partition
CREATE TABLE tab_partition(`dt` Date, `v` UInt8)
ENGINE = MergeTree PARTITION BY toYYYYMM(dt) ORDER BY v;
insert into tab_partition(dt,v) values ('2020-02-11',1),('2020-02-13',2);
insert into tab_partition(dt,v) values ('2020-04-11',3),('2020-04-13',4);
insert into tab_partition(dt,v) values ('2020-09-11',5),('2020-09-10',6);
insert into tab_partition(dt,v) values ('2020-10-12',7),('2020-10-09',8);
insert into tab_partition(dt,v) values ('2020-02-14',9),('2020-02-15',10);
insert into tab_partition(dt,v) values ('2020-02-11',23),('2020-02-13',45);
MergeTree 存储引擎在写入数据之后生成对应的分区文件为:
MergeTree的分区目录是在写入数据的过程中被创建出来,每insert一次,就会创建一批次分区目录。也就是说如果仅创建表结构,是不会创建分区目录的,因为木有数据。
MergeTree数据分区目录命名规则 其规则为
PartitionID_MinBlockNum_MaxBlockNum_Level
比如 202002_4_4_0
其中 202002 是分区ID ,4_4
对应的是
最小的数据块编号和最大的数据块编号,最后的_0 表示目前分区合并的层级。
各部分的含义及命名规则如下:
PartitionID:该值由 insert 数据时分区键的值来决定。分区键支持使用任何一个或者多个字段组合表达式,针对取值数据类型的不同,分区ID的生成逻辑目前有四种规则:
不指定分区键:如果建表时未指定分区键,则分区ID默认使用all,所有数据都被写入all分区中 整型字段:如果分区键取值是整型字段,并且无法转换为YYYYMMDD的格式,则会按照该整型字段的字符形式输出,作为分区ID取值 日期类型:如果分区键属于日期格式,或可以转换为YYYYMMDD格式的整型,则按照YYYYMMDD格式化后的字符形式输出,作为分区ID取值 其他类型:如果使用其他类似Float、String等类型作为分区键,会通过对其插入数据的128位Hash值作为分区ID的取值
MinBlockNum 和 MaxBlockNum: BlockNum 是一个整型的自增长型编号,该编号在单张MergeTree表中从1开始全局累加,当有新的分区目录创建后,该值就加1,对新的分区目录来讲,MinBlockNum 和 MaxBlockNum 取值相同。例如上面示例数据为202002_1_1_0
202002_1_5_1
,但当分区目录进行合并后,取值规则会发生变化, MinBlockNum 取同一分区所欲目录中最新的 MinBlockNum值。MaxBlockNum 取同一分区内所有目录中的最大值。
Level: 表示合并的层级。相当于某个分区被合并的次数,它不是以表全局累加,而是以分区为单位,初始创建的分区,初始值为0,相同分区ID发生合并动作时,在相应分区内累计加1。
MergeTree数据分区合并规则
随着数据的写入MergeTree 存储引擎会很多分区目录。如果分区目录数太多怎么办?
因为Clickhouse 的MergeTree 存储引擎是基于 LSM 实现的。MergeTree可以通过分区合并将属于相同分区的多个目录合并为一个新的目录(官方描述在10到15分钟内会进行合并,也可直接执行optimize语句),已经存在的旧目录(也即system.parts表中activie为0的分区)在之后某个时刻通过后台任务删除(默认8分钟).
####分区合并 我们回顾之前创建的表的分区目录
# ls
202002_1_1_0 202004_2_2_0 202009_3_3_0
202002_4_4_0 202002_5_5_0
手工触发分区合并
qabb-qa-ch00 :) optimize table tab_partition;
OPTIMIZE TABLE tab_partition
Ok.
0 rows in set. Elapsed: 0.003 sec.
qabb-qa-ch00 :) select partition,name,part_type, active from system.parts where table ='tab_partition';
┌─partition─┬─name─────────┬─part_type─┬─active─┐
│ 202002 │ 202002_1_1_0 │ Wide │ 0 │
│ 202002 │ 202002_1_5_1 │ Wide │ 1 │
│ 202002 │ 202002_4_4_0 │ Wide │ 0 │
│ 202002 │ 202002_5_5_0 │ Wide │ 0 │
│ 202004 │ 202004_2_2_0 │ Wide │ 1 │
│ 202009 │ 202009_3_3_0 │ Wide │ 1 │
└───────────┴──────────────┴───────────┴────────┘
6 rows in set. Elapsed: 0.003 sec.
其中 active 为1表示经过合并之后的最新分区,为0 则表示旧分区,查询时会自动过滤 active=0 的分区。
我们通过 分区 202002 最新的分区目录202002_1_5_1
看到合并分区新目录的命名规则如下:
PartitionID:分区ID保持不变 MinBlockNum:取同一个分区内所有目录中最小的MinBlockNum值 MaxBlockNUm:取同一个分区内所有目录中最大的MaxBlockNum值 Level:取同一个分区内最大Level值并加1
合并之后的目录结构如下:
小结
本文可以认为是《ClickHouse 原理解析与应用实践》的学习笔记 ^_^。通过案例介绍了 MergeTree的分区产生的机制,命名规则,以及合并的基本过程。有兴趣的朋友可以自己动手实践一下。
-The End-
- 【AngularJS】—— 2 初识AngularJs(续)
- 【AngularJS】—— 3 我的第一个AngularJS小程序
- 【Spring实战】—— 2 构造注入
- 共享单车运维“朋友圈”越来越宽,乱停乱放现象有望改善吗?
- 【Spring实战】—— 15 Spring JDBC模板使用
- 前端开发总览
- 【Spring实战】—— 16 基于JDBC持久化的事务管理
- 【Spring实战】—— 4 Spring中bean的init和destroy方法讲解
- 基于AngularJS的过滤与排序
- 【Spring实战】—— 5 设值注入
- 科学家预测:未来100万年人类将变成半机械人类
- 【Spring实战】—— 8 自动装配
- 【Spring实战】—— 7 复杂集合类型的注入
- 【Spring实战】—— 6 内部Bean
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Mybatis-generator 逆向工程 自定义PO,xml,mapper,example
- 高速上云/网络穿透/视频上云网关EasyNTS组网服务登录状态检测优化记录
- 树莓派基础实验38:逻辑分析仪分析PWM、UART信号
- 【终端设备】视频上云/网络穿透EasyNTS云组网硬件终端无法单独修改账号的优化方式
- 测试环境问题排查的那些事儿
- RTSP流媒体协议视频平台EasyNVR和EasyNTS智能云组网同一浏览器运行为什么会导致EasyNTS无法登陆?
- Java:手写线程安全LRU缓存X探究影响命中率的因素
- 视频上云/网络穿透/网络映射服务EasyNTS设备管理为什么会出现无法搜索到设备的情况?
- 快速打造属于你的接口自动化测试框架
- 大数据下的质量体系建设
- PostgreSQL 日志系统 及 设置错误导致磁盘塞满案例
- 六、乘胜追击,将剩下的Git知识点搞定
- 树莓派基础实验39:解析无线电接收机PWM、SBUS信号
- nodejs源码分析第十九章 -- udp模块
- Spark Extracting,transforming,selecting features