ClickHouse中的MergeTree表引擎详解

news2024/12/23 8:42:51

MergeTree的特点

MySQL中最强大的表引擎是InnoDB,ClickHouse中最强大的表引擎是MergeTree以及该系列中的其他引擎。MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不断修改(重写)已存储的数据,这种策略会高效很多。

MergeTree的主要特点有以下几点:

  • 存储的数据按主键排序
  • 如果指定了分区键的话,可以使用分区
  • 支持数据副本
  • 支持数据采样

MergeTree如何存储数据

当数据被写入到MergeTree表中时,会创建多个数据片段并按照主键排序,根据官网的例子,如果主键是(CounterID, Date),数据片段中的数据会首先按照CounterID排序,CounterID相同的数据按照Date排序。

不同分区的数据会被分成不同的片段,ClickHouse 在后台合并数据片段以便更高效存储。不同分区的数据片段不会进行合并。合并机制并不保证具有相同主键的行全都合并到同一个数据片段中。

数据片段的格式有下面两种

  • Wide:每一列都会在文件系统中存储为单独的文件
  • Compact:所有列都存储在一个文件中,可以提高插入量少插入频率频繁时的性能

min_bytes_for_wide_part 和 min_rows_for_wide_part 控制数据存储格式,如果数据片段中的字节数或行数少于相应的设置值,数据片段会以 Compact 格式存储,否则会以 Wide 格式存储。

每个数据片段在逻辑上会被分成多个颗粒(granules),granules是ClickHouse进行数据查询时的最小不可分割的数据集,也是MergeTree查询如此快的其中一个原因。每个颗粒的第一行通过该行的主键值进行标记, ClickHouse 会为每个数据片段创建一个索引文件来存储这些标记。对于每列,无论它是否包含在主键当中,ClickHouse 都会存储类似标记。这些标记让您可以在列文件中直接找到数据。

颗粒的大小通过表引擎参数 index_granularity 和 index_granularity_bytes 控制。index_granularity 控制每个颗粒的行数,index_granularity_bytes 控制每个颗粒的大小。

通过例子展示数据存储

数据准备

首先建一张表并插入一些数据

CREATE database if not exists ck_test;

create table ck_test.user
(
    id UInt32,
    name String,
    grade UInt32,
    l_date Date
)
ENGINE = MergeTree 
PARTITION BY toYYYYMM(l_date)
PRIMARY KEY(id)
ORDER BY id
SETTINGS index_granularity=3,
min_rows_for_wide_part = 0, 
min_bytes_for_wide_part = 0;

INSERT into ck_test.user values(1,'张三',88,'2023-04-01'),(2,'李四',90,'2023-04-02'),(2,'王五',93,'2023-04-03'),(3,'赵六',80,'2023-04-04'),(4,'孙七',99,'2023-04-05');
INSERT into ck_test.user values(5,'张三',88,'2023-05-01'),(6,'李四',90,'2023-05-02'),(7,'王五',93,'2023-05-03'),(8,'赵六',80,'2023-05-04'),(9,'孙七',99,'2023-05-05');

为了方便演示,增加了index_granularity=2、min_rows_for_wide_part = 0、min_bytes_for_wide_part = 0三个参数。
index_granularity=2表示每两行就会生成一个颗粒文件
min_rows_for_wide_part = 0、min_bytes_for_wide_part = 0 主要为了让数据片段都以 Wide 类型存储,更能理解列式存储。否则少量数据就只会被存储在data.bin这一个文件里。

物理存储

ClickHouse默认的数据存储地址在/var/lib/clickhouse/data
image.png
按数据库分成不同的文件夹,进入每个文件夹,每张表又被分成多个文件夹
image.png
进入user文件夹内部,可以看到按不同的分区又被分成了不同文件夹
image.png
随便进入一个分区,可以看到真正存储数据的结构
image.png
*.bin 是列数据文件,如果是Wide格式存储,每一列就会生成一个bin文件,如果是Compact格式,就只会生成一个data.bin文件。
*.mrk2 是mark 文件,目的是快速定位 bin 文件数据位置。
minmax_l_date.idx 是分区键索引文件,主要是为了加速分区字段的查询。
primay.idx 主键索引文件,目的是加速主键查找。
*.txt文件存储了一些记录信息,比如count.txt存储这个分区下的总数,columns.txt存储了列信息。

bin和mrk2

MergeTree 在单个分区内的数据只有一份 *.bin,列名是这份数据文件的名称,bin文件会以排序键进行对齐。
Granule会把bin文件根据设定的 index_granularity 分成多个颗粒,然后通过 *.mrk2 记录颗粒信息。
以id这个字段为例,在建表时设置了 index_granularity=3,所以每三行数据会组成一个颗粒。

MergeTree中的主键索引

MergeTree 的查询速度主要也依赖于索引,MergeTree中的索引分为主键索引和跳数索引。主键索引对应的物理文件是 primary.idx 。
MergeTree 的主键索引采用的是稀疏索引的方式,这种稀疏索引能更快地在海量数据中实现快速检索。MergeTree 的主键索引会选取每个 granule 中的最小值作为主键标识,对应的效果图如下:

主键索引的稀疏度依赖于 index_granularity 的大小,基于稀疏索引,Merge可以快速定位到数据所在的颗粒,并快速定位到数据。
MergeTree 的另外一种索引格式是跳数索引,跳数索引会单独讲解。

使用MergeTree建一张表

了解原理之后,来看看MergeTree下的建表语句,属性中的字段在增删改查部分讲了,这里主要介绍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
[PARTITION BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
[SETTINGS name=value, ...]

ENGINE = MergeTree() 指定了表所采用的引擎
ORDER BY 是排序键,如果没有使用 PRIMARY KEY 显式指定的主键,ClickHouse 会使用排序键作为主键。
PARTITION BY 是分区键,分区后的数据会被放在不同的文件中,ClickHouse官方文档中说在大多数情况下不需要使用分区键,如果用了分区键也不需要使用比月更细粒度的分区,通过 toYYYYMM(date_column) 实现按月分区。
PRIMARY KEY 指定主键。
SAMPLE BY 用于指定采样表达式,ClickHouse支持近似查询,实现方式就是通过采样,比如计算所有访问的统计信息,只需对所有访问的1/10分数执行查询,然后将结果乘以10即可。采样的实现可以参考官网:
https://clickhouse.com/docs/zh/sql-reference/statements/select/sample
TTL 用于用于设置值的生命周期,可以为整张表设置,也可以给单个表设置,更加详细地关于TTL的认识可以参考下面这个文档:
https://clickhouse.com/docs/zh/engines/table-engines/mergetree-family/mergetree#mergetree-column-ttl
SETTINGS 用于控制MergeTree的额外参数,Settings按需进行调整,没有特殊需求一般不用手动调整:

  • index_granularity — 索引颗粒度,默认值8192 ,在上面介绍存储格式时已经用到了。
  • index_granularity_bytes — 索引粒度,以字节为单位,默认值: 10Mb。如果想要仅按数据行数限制索引粒度, 请设置为0(不建议)。
  • min_index_granularity_bytes - 允许的最小数据粒度,默认值:1024b。该选项用于防止误操作,添加了一个非常低索引粒度的表。
  • enable_mixed_granularity_parts — 是否启用通过 index_granularity_bytes 控制索引粒度的大小。在19.11版本之前, 只有 index_granularity 配置能够用于限制索引粒度的大小。当从具有很大的行(几十上百兆字节)的表中查询数据时候,index_granularity_bytes 配置能够提升ClickHouse的性能。如果您的表里有很大的行,可以开启这项配置来提升SELECT 查询的性能。
  • use_minimalistic_part_header_in_zookeeper — ZooKeeper中数据片段存储方式 。如果use_minimalistic_part_header_in_zookeeper=1 ,ZooKeeper 会存储更少的数据。
  • min_merge_bytes_to_use_direct_io — 使用直接 I/O 来操作磁盘的合并操作时要求的最小数据量。合并数据片段时,ClickHouse 会计算要被合并的所有数据的总存储空间。如果大小超过了 min_merge_bytes_to_use_direct_io 设置的字节数,则 ClickHouse 将使用直接 I/O 接口(O_DIRECT 选项)对磁盘读写。如果设置 min_merge_bytes_to_use_direct_io = 0 ,则会禁用直接 I/O。默认值:10 * 1024 * 1024 * 1024 字节。
  • merge_with_ttl_timeout — TTL合并频率的最小间隔时间,单位:秒。默认值: 86400 (1 天)。
  • write_final_mark — 是否启用在数据片段尾部写入最终索引标记。默认值: 1(不要关闭)。
  • merge_max_block_size — 在块中进行合并操作时的最大行数限制。默认值:8192
  • storage_policy — 存储策略。
  • min_bytes_for_wide_part,min_rows_for_wide_part 在数据片段中可以使用Wide格式进行存储的最小字节数/行数。
  • max_parts_in_total - 所有分区中最大块的数量。
  • max_compress_block_size - 在数据压缩写入表前,未压缩数据块的最大大小。
  • min_compress_block_size - 在数据压缩写入表前,未压缩数据块的最小大小。
  • max_partitions_to_read - 一次查询中可访问的分区最大数。

参考文档

https://clickhouse.com/docs/zh/engines/table-engines/mergetree-family/mergetree
https://bohutang.me/2020/06/26/clickhouse-and-friends-merge-tree-disk-layout/

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

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

相关文章

基于属性推理辅助的计算机辅助肺结核诊断

文章目录 Computer-Aided Tuberculosis Diagnosis with Attribute Reasoning Assistance摘要方法Attribute Feature RepresentationFeature Interaction 实验结果 Computer-Aided Tuberculosis Diagnosis with Attribute Reasoning Assistance 摘要 本文首先提出了一种新的大…

FE_CSS 常见布局技巧

1 巧妙运用浮动元素不会压住文字的特性 float: left; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta ht…

【LeetCode】121. 买卖股票的最佳时机

121. 买卖股票的最佳时机&#xff08;简单&#xff09; 思路 遍历数组&#xff0c;在每一个位置 i 时&#xff0c; 记录当前位置之前的最低价格&#xff0c;然后将当前价格作为售出价格&#xff0c;查看当前收益是不是最大收益即可。如果最大收益小于等于 0 &#xff0c;则返回…

【NVM】使用NVM实现不同nodejs版本的自由切换(NVM安装教程使用手册):

文章目录 一、NVM的下载二、NVM安装三、NVM使用1. 设置nvm环境2.安装nodejs3.使用或切换nodejs版本 四、建议五、nvm命令总结 一、NVM的下载 注意路径不要出现中文和空格 安装包地址&#xff1a;https://github.com/coreybutler/nvm-windows/releases 二、NVM安装 三、NVM使用…

【嵌入式笔/面试】嵌入式软件基础题和真题总结——网络相关

在学习的时候找到几个十分好的工程和个人博客&#xff0c;先码一下&#xff0c;内容都摘自其中&#xff0c;有些重难点做了补充&#xff01; 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面…

Springcloud快速复习--注册中心

按照个人的习性,分布式我学习完以后一定会忘为此写次笔记自己快速复习 目录 Springcloud介绍注册中心–Eureka注册中心–Nacos Springcloud介绍及微服务介绍 为什么学? 也不是以前的单体架构被淘汰而是,当业务足够大型,进行优化 单体架构&#xff1a;将业务的所有功能集中在…

数据分析之Numpy

文章目录 1. Anaconda安装2. juypter3. numpy简介4. numpy数组4.1 ndarray对象4.2 array创建数组4.3 arange区间数组4.4 linspace等差数列4.5 logspace等比数列4.6 numpy.empty4.7 numpy.zeros4.8 numpy.ones4.9 numpy.zeros_like4.10 numpy.ones_like4.11 numpy.asarray4.12 n…

汉诺塔的非递归算法

对于汉诺塔问题&#xff0c;我们都普遍认为这个是一个典型的递归问题&#xff0c;然而递归需要使用到系统对应的栈&#xff0c;开销比较大&#xff0c;因此我在想使用非递归算法来解决它&#xff0c;然而网上绝大部分的教程都是自己模拟了一个栈&#xff0c;因此我在考虑写一篇…

【C++初阶】:内联函数

内联函数 一.宏函数二.内联函数三,是否成为内联函数四.内联函数的跨文件使用 一.宏函数 在c语言中&#xff0c;如果一个函数较短并且会被重复使用&#xff0c;那么我们就可以把该函数换成一个宏函数。 贴个小知识&#xff0c;宏函数有许多的坑也是面试官喜欢考的点&#xff0c;…

如何使用美颜SDK制作美妆相机?美颜SDK代码分析

随着时代的发展&#xff0c;人们对于自己的外貌要求越来越高&#xff0c;因此美颜相机、美妆相机等软件也逐渐兴起。其中&#xff0c;美妆相机是一种可以实现“快速上妆效果”的美颜工具&#xff0c;而美颜SDK则是实现美妆相机的核心技术之一。本文将介绍如何使用美颜SDK制作美…

你怎么看 App响应时间优化这事?

作者&#xff1a;xuexiangjys 响应时间&#xff0c;它是用来衡量系统运行效率的一个重要指标。评价一个应用的响应时间&#xff0c;可以从用户感知和系统性能这两个角度来考量。 响应时间的长短&#xff0c;可能影响用户对某个功能、某个应用、乃至某个系统的使用。毕竟如果有选…

VS2022配置OpenGL+GLAD

Glew&#xff08;The OpenGL Extension Wrangler Library&#xff09;是对底层OpenGL接口的封装&#xff0c;可以让你的代码跨平台。Glad与Glew作用相同&#xff0c;可以看作它的升级版。 Freeglut&#xff08;OpenGL Utility Toolkit&#xff09;主要用于创建并管理窗口和Ope…

Windows逆向安全(一)之基础知识(十五)

指针二 先前介绍了指针的一些基本的知识&#xff0c;但都没有提到地址的概念&#xff0c;下面承接之前的笔记&#xff0c;继续学习指针 下面要介绍三个相关的内容&#xff1a;获取变量的数据类型 、 取变量地址和取地址中存储的数据 获取变量的数据类型 在C语言中可以使用下…

Sleep:预测认知能力的最佳纺锤波检测参数

导读 目的&#xff1a;睡眠纺锤波的改变与认知障碍有关。这一发现增加了人们对识别基于睡眠的认知和神经退行性疾病生物标志物(包括睡眠纺锤波)的兴趣。然而&#xff0c;围绕纺锤波定义和算法参数设置的灵活性带来了方法上的挑战。本研究的目的是描述纺锤波检测参数设置如何影…

Dynamic Slicing for Deep Neural Networks

0、摘要 程序切片已广泛应用于各种软件工程任务中。然而&#xff0c;现有的程序切片技术只能处理由指令和变量构建的传统程序&#xff0c;而不能处理由神经元和突触组成的神经网络。在本文中&#xff0c;我们提出了 NNSlicer&#xff0c;这是第一种基于数据流分析的深度神经网络…

android studio shape形状图形

1.创建shape 2定义椭圆 <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk/res/android"android:shape"oval"><!--指定形状椭圆--><!--指定形状内部颜色--><…

Ubuntu与window实现文件共享——Samba使用

前言 &#xff08;1&#xff09;我们在使用Linux开发的时候&#xff0c;因为Linux中写程序没有Windows的工具方便&#xff0c;所以经常是先在windows环境下编写程序&#xff0c;之后再将文件上传给Linux进行编译。 &#xff08;2&#xff09;这样就存在一个问题&#xff0c;因为…

vue使用Howler实现音乐播放器

vue使用Howler实现音乐播放器 前言一、引入依赖二、封装组件 前言 本文使用Howler.js进行播放。使用siriwave做的播放动画具体文档地址如下 名称地址Howlerhttps://howlerjs.com/siriwavehttps://github.com/kopiro/siriwave 最后实现效果如下&#xff1a; 实现暂停、开始、…

教你如何根据需求编写测试用例,不用写一行代码,使用ChatGPT4自动完成。

首先来张效果图&#xff0c;需求我是放到requirements.txt文档里&#xff0c;输出的测试用例是放到test_case1.txt&#xff0c;整个代码我是让ChatGPT4自动给我写的。 我用的prompt提示语是&#xff1a; 我的想法是这样&#xff0c;通过Python代码&#xff0c;和API keys来实现…

传统制造企业在引入项目管理机制时项目组织结构的重要性

在传统的工业设备制造行业,针对以订单项目为驱动的业务模式,建立一套成熟完备的项目管理机制十分重要,同时也是企业提升自身管理水平精细度的内在要求。项目管理作为外企普遍应用的成熟管理模式,如何将其引入并与民企现存的传统职能型管理模式融合,实现成功嫁接,值得大家思考并…