详解 ClickHouse 的表引擎

一、简介

  • 表引擎决定了如何存储表的数据。包括:
    • 数据的存储方式和位置,写到哪里以及从哪里读取数据
    • 支持哪些查询以及如何支持
    • 并发数据访问
    • 索引的使用(如果存在)
    • 是否可以执行多线程请求
    • 数据复制参数
  • 表引擎的使用方式:必须显式在创建表时定义该表使用的引擎,以及引擎使用的相关参数。特别注意:表引擎的名称大小写敏感

二、TinyLog

​ Log Farmily 的表引擎之一,以列文件的形式保存在磁盘上,不支持索引,没有并发控制。一般保存少量数据的小表,生产环境上作用有限。可以用于平时练习测试用。

create table t_tinylog 
( id String, name String
) 
engine=TinyLog;

三、Memory

​ 内存引擎,数据以未压缩的原始形式直接保存在内存当中,服务器重启数据就会消失。读写操作不会相互阻塞,不支持索引。简单查询下有非常非常高的性能表现(超过 10G/s)。一般用到它的地方不多,除了用来测试,就是在需要非常高的性能,同时数据量又不太大(上限大概 1 亿行)的场景。

四、MergeTree

重点

​ MergeTree Farmily 的表引擎之一,ClickHouse 中最强大的表引擎系列,支持索引和分区,地位相当于 innodb 之于 Mysql。基于 MergeTree 还衍生出了很多非常有特色的引擎(*MergeTree)

1. 简单使用

  • 创建一个 clickhouse 表并指定表引擎

    create table t_order_mt
    (id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime
    )
    engine=MergeTree
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id, sku_id);
    
  • 插入数据

    insert into t_order_mt values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');
    

2. 表引擎参数

MergeTree 有很多参数(绝大多数用默认值即可),但是有三个参数是更加重要的

2.1 partition by

分区参数,可选,不指定则表只有一个分区,目录名称为 all

  • 语法:partition by (column)

  • 分区的目的主要是降低扫描的范围,优化查询速度

  • 分区表是以分目录的形式存储数据

    #表在磁盘的目录结构 
    t_order_mt #表目录20200601_1_1_0 20200602_2_2_0detached #卸载目录format_version.txt #版本文件#分区目录名组成:分区值_最小分区块编号_最大分区块编号_合并层级#分区值:分区值由 partition by 指定的分区字段决定#未指定分区字段:分区值为 all#整型的分区字段:以该字段整型值的字符串形式作为分区值#日期型或可转成日期的分区字段:以该字段值的字符串形式作为分区值#String、Float等类型的分区字段:通过128位的Hash算法取字段的Hash值作为分区值#最小分区块编号:自增,从1开始向上递增,每产生一个分区目录就向上递增一个数字#最大分区块编号:新创建的分区的最大分区块编号=最小分区块编号#合并层级:被合并的次数#分区目录文件:
    20200601_1_1_0checksums.txt #校验文件,用于检验各个文件的正确性。存放各个文件的size和hash值columns.txt #表的列信息count.txt #表的数据条数data.bin  #数据文件data.mrk3 #标记文件,记录列的偏移量,在idx文件和bin文件之间起到桥梁作用。如果以mrk2开头表示该表启用了自适应索引间隔default_compression_codec.txt #默认的压缩方式minmax_create_time.idx #分区键的最大最小值partition.dat #分区文件primary.idx #主键索引文件,用于加快查询效率
    
  • 分区后,面对涉及跨分区的查询统计,ClickHouse 会以分区为单位并行处理

  • 任何一个批次的数据写入都会产生一个临时分区,不会纳入任何一个已有的分区。写入后的某个时刻(大概 10-15 分钟后),ClickHouse 会自动执行合并操作(等不及也可以手动通过 optimize 执行),把临时分区的数据,合并到已有分区中

    --第一次插入数据生成的分区目录为:
    20200601_1_1_0
    20200602_2_2_0--再次执行数据插入
    insert into t_order_mt values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');--此时的表分区目录为:
    20200601_1_1_0
    20200601_3_3_0
    20200602_2_2_0
    20200602_4_4_0--手动执行合并
    optimize table t_order_mt final;
    --optimize table t_order_mt partition '20200601' final; --合并指定分区--表分区目录变为:
    20200601_1_1_0  --过期数据,后续会被清理
    20200601_1_3_1  --合并后的目录
    20200601_3_3_0
    20200602_2_2_0
    20200602_2_4_1
    20200602_4_4_0
    
2.2 primary key

主键参数,可选

  • 语法:primary key (column1[,column2...])
  • clickhouse 的主键不同于其他数据库,它没有设置唯一约束,因此主键列可以存在相同的值
  • clickhouse 的主键提供了数据的一级索引,采用稀疏索引进行保存,在查询时通过对主键进行某种形式的二分查找,能够定位到对应的 index granularity(索引粒度),避免了全表扫描。
  • clickhouse 中的 MergeTree 默认的索引粒度是 8192。官方不建议修改这个值,除非该列存在大量重复值,比如在一个分区中几万行才有一个不同数据。
  • 稀疏索引的好处就是可以用很少的索引数据,定位更多的数据,代价就是只能定位到索引粒度的第一行,然后再进行扫描。
2.3 order by

排序参数,必须设置

  • 语法:order by (column1[,column2...])
  • order by 设定了分区内的数据按照哪些字段顺序进行有序保存,分区间还是无序的
  • 主键必须是 order by 字段的前缀字段,如 order by 字段是 (id,sku_id),那么主键必须是 id 或者 (id,sku_id)
2.4 二级索引

二级索引能够为非主键字段的查询发挥作用

  • 在 clickhouse v20.1.2.4 版本中二级索引还是实验性的,使用前需要设置,之后的版本则默认开启了

    set allow_experimental_data_skipping_indices=1;
    
  • 语法:

    INDEX index_name column_name TYPE [minmax] GRANULARITY num--INDEX:指定二级索引的名称和对应的表字段
    --TYPE:指定二级索引的类型,一般为 minmax
    --GRANULARITY:设定二级索引对于一级索引粒度的粒度,即 num 个一级索引的分块组成一个二级索引的分块
    
  • 使用方法:

    --创建带二级索引的表
    create table t_order_mt2
    (id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime,INDEX a total_amount TYPE minmax GRANULARITY 5
    ) 
    engine=MergeTree
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id, sku_id);--插入数据
    insert into t_order_mt2 values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');
    
  • 测试二级索引效果

    clickhouse-client --send_logs_level=trace <<< 'select * from t_order_mt2 where total_amount > toDecimal32(900., 2)';
    
2.5 数据TTL

TTL 即 Time To Live,MergeTree 提供了可以管理数据表或者列的生命周期的功能。

  • 列级别 TTL

    --语法:
    column_name1 column_type TTL column_name2 + interval num [SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|QUARTER|YEAR]--column_name2:不能是主键字段,且字段类型必须为 Date 或者 Datetime 类型,推荐使用分区的日期字段--1. 建表时设置
    create table t_order_mt3
    (id UInt32,sku_id String,total_amount Decimal(16,2) TTL create_time + interval 10 SECOND,create_time Datetime
    ) 
    engine =MergeTree
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id, sku_id);--2. 在已有表上设置
    alter table t_order_mt2 modify column total_amount Decimal(16,2) TTL create_time + interval 10 SECOND;--插入数据
    insert into t_order_mt3 values
    (106,'sku_001',1000.00,'2023-09-10 15:02:30'),
    (107,'sku_002',2000.00,'2023-09-10 15:02:40'),
    (110,'sku_003',600.00,'2023-09-10 15:02:50');--手动合并,查看效果,TTL到期后,指定的字段数据变为该类型默认值 0.00
    optimize table t_order_mt3 final;
    select * from t_order_mt3;
    
  • 表级别 TTL

    --语法:
    TTL column_name + interval num [SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|QUARTER|YEAR]
    [DELETE|TO DISK 'path'|TO VOLUME 'path']
    [WHERE conditions]
    [GROUP BY key_expr [SET v1 = aggr_func(v1),...]]--column_name:不能是主键字段,且字段类型必须为 Date 或者 Datetime 类型,推荐使用分区的日期字段
    --可以指定过期数据是删除(默认)还是移动到磁盘等--1. 建表时设置
    create table t_order_mt4
    (id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime
    ) 
    engine =MergeTree
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id, sku_id)
    TTL create_time + interval 10 SECOND;--2. 在已有表上设置
    alter table t_order_mt3 modify TTL create_time + interval 10 SECOND;--插入数据
    insert into t_order_mt4 values
    (106,'sku_001',1000.00,'2023-09-10 15:12:30'),
    (107,'sku_002',2000.00,'2023-09-10 15:12:40'),
    (110,'sku_003',600.00,'2023-09-10 15:12:50');--手动合并,查看效果,TTL到期后,对应数据行记录被删除
    optimize table t_order_mt4 final;
    select * from t_order_mt4;
    

五、ReplacingMergeTree

​ ReplacingMergeTree 是 MergeTree 引擎的一个变种,它的存储特性完全继承 MergeTree,只是多了一个去重的功能。 但 ReplacingMergeTree 去重能力有限, ReplacingMergeTree 适用于在后台清除重复的数据以节省空间,但是它不保证表中没有重复的数据出现。

1. 功能说明

  • ReplacingMergeTree 是通过 order by 参数指定的字段作为唯一约束进行去重的
  • 去重只能在同一分区的内部进行,不能执行跨分区的去重
  • 去重的时机:a) 在 clickhouse 新版本中同一批次的数据插入时会进行去重;b) 分区进行自动或手动合并操作时会进行去重
  • 去重后数据的保留:a) 当指定了版本字段时,会将版本字段值最大的那条数据保留,若版本字段最大值数据有多条则保留顺序为最后插入的那条数据;b) 没有指定版本字段时则保留顺序为最后插入的那条数据

2. 简单使用

  • 创建一张表并指定引擎为 ReplacingMergeTree

    create table t_order_rmt
    (id UInt32,sku_id String,total_amount Decimal(16,2) ,create_time Datetime
    ) 
    engine=ReplacingMergeTree(create_time)
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id, sku_id);--(create_time)为指定版本字段,一般建议为日期类型字段,可以确定重复数据的保留规则
  • 向表中插入数据

    insert into t_order_rmt values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');
    
  • 查询数据

    select * from t_order_rmt;--在新版本中同一批次数据插入时会进行数据去重,所以总共只有 4 条数据
    --在老版本中则不会进行去重,所以会查询出 6 条数据
    
  • 再次向表中插入数据并查询

    insert into t_order_rmt values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');select * from t_order_rmt;--此时分区未合并,会查询出 8 条数据--执行分区合并
    optimize table t_order_rmt final;--再次进行查询,重复数据已经去除,查询出 4 条数据
    

六、SummingMergeTree

​ SummingMergeTree 是 MergeTree 引擎的一个变种,它扩展的功能是能够对分区内的同一维度的数据进行预聚合操作,从而减少存储空间的耗费和降低查询时聚合的开销。

1. 功能说明

  • SummingMergeTree 是通过 order by 参数指定的字段作为聚合维度
  • 聚合数据列:a) 可以通过 SummingMergeTree(column1,…) 指定进行聚合的字段,可以指定多个,但所有字段必须是数值类型;b) 未指定聚合字段则会对表中所有非维度的数值类型字段进行预聚合操作
  • 聚合后各字段的保留:维度字段不变,数值字段为汇总后的值,其他字段保留最早插入时的那个值
  • 预聚合只能在同一分区内进行,不能执行跨分区的预聚合
  • 预聚合的时机:a) 在 clickhouse 新版本中同一批次的数据插入时会进行预聚合;b) 分区进行自动或手动合并操作时会进行预聚合
  • 注意:在进行查询获取汇总值时还是需要使用 sum() 聚合函数,因为表中可能会包含一些还没来得及预聚合的临时明细

2. 简单使用

  • 创建一张表并指定引擎为 SummingMergeTree

    create table t_order_smt
    (id UInt32,sku_id String,total_amount Decimal(16,2) ,create_time Datetime
    ) 
    engine=SummingMergeTree(total_amount)
    partition by toYYYYMMDD(create_time)
    primary key (id)
    order by (id,sku_id );--(total_amount)是指定要进行汇总的字段,可以指定多个
    
  • 插入数据并查询

    insert into t_order_smt values
    (101,'sku_001',1000.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 11:00:00'),
    (102,'sku_004',2500.00,'2020-06-01 12:00:00'),
    (102,'sku_002',2000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',12000.00,'2020-06-01 13:00:00'),
    (102,'sku_002',600.00,'2020-06-02 12:00:00');select * from t_order_smt;--新版本同一批次插入时会直接进行汇总,所以查询 20200601 分区内 102,sku_002 维度的 total_amount 字段的值为汇总值 16000.00,create_time 字段值为最早插入的值 2020-06-01 11:00:00
    
  • 再次插入数据并手动合并分区

    insert into t_order_smt values (101,'sku_001',2000.00,'2020-06-01 13:00:00');select * from t_order_smt; --分区未合并,101,'sku_001' 维度的数据有两条optimize table t_order_smt final;select * from t_order_smt;--分区合并,同一维度数据进行汇总,101,'sku_001' 维度的 total_amount 值为 3000.00,create_time 字段值为 2020-06-01 12:00:00
    

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

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

相关文章

迭代器模式观察者模式

文章目录 1.引出迭代器模式1.展示院系结构2.传统方式 2.迭代器模式解决院系结构展示问题1.基本介绍2.原理类图3.类图4.代码实现1.Department.java 存储信息的对象2.College.java 被迭代的类型接口3.ComputerCollege.java 被迭代的具体实现类&#xff0c;存储数据并将其在创建迭…

CNware虚拟化平台功能介绍:虚拟机业务连续性保护,确保核心业务持续运行,构筑稳健的数字防线

全球数字化转型的大潮中&#xff0c;虚拟化技术已成为企业IT架构的基石。据Gartner预测&#xff0c;到2026年&#xff0c;全球90%以上的组织将采用某种形式的虚拟化技术。虚拟化环境的广泛应用&#xff0c;不仅提升了资源利用率、降低了成本&#xff0c;更极大地增强了业务灵活…

forwhile(Python)

文章目录 前言一、for二、while 前言 循环&#xff1a;就是让指定的代码重复的执行。 一、for for 循环可以遍历任何可迭代对象&#xff0c;如一个列表或者一个字符串。 forfor i in list:循环主体for i in [1, 2, 3, 4, 5]:print(i)**************************************…

“管式加热炉简单控制系统和串级控制系统设计与Matlab仿真”,高分资源,匠心制作,下载可用。强烈推荐!!!

“管式加热炉简单控制系统和串级控制系统设计与Matlab仿真”毕业设计&#xff0c;高分资源&#xff0c;匠心制作&#xff0c;下载可用。强烈推荐&#xff01;&#xff01;&#xff01; 1.控制目标 加热炉的任务是把原油加热到一定温度&#xff0c;以保证下道工艺的顺利进行。…

企业如何通过数据资产入表与融资加速数字化转型

数据作为五大生产要素之一&#xff0c;是数字经济发展的基础。如何对数据资产进行确权、核算和变现&#xff0c;已成为数字经济时代的难点和热点。随着“数据资产入表”的提出与实践&#xff0c;这一领域迎来了新的变化与机遇。 一、什么是数据资产入表 在我国&#xff0c;数据…

二种方法轻松提取音频中的钢琴声音

在音乐制作、音频编辑或是纯粹的音乐爱好者的世界里&#xff0c;有时我们需要从复杂的音乐编排中抽取出特定乐器的声音&#xff0c;比如那悠扬的钢琴旋律。这不仅能帮助我们更好地理解音乐的结构&#xff0c;还能在创作过程中提供灵感。本文将介绍两种简单有效的方法&#xff0…

如何在Windows 11上设置默认麦克风和相机?这里有详细步骤

如果你的Windows 11计算机上连接了多个麦克风或网络摄像头&#xff0c;并且希望自动使用特定设备&#xff0c;而不必每次都在设置中乱动&#xff0c;则必须将首选设备设置为默认设备。我们将向你展示如何做到这一点。 如何在Windows 11上更改默认麦克风 有两种方法可以将麦克…

第 28 篇 : SSH秘钥登录

1 生成秘钥 ssh-keygen -t rsa ls -a ./.ssh/一直回车就行了 2. 修改配置 vi /etc/ssh/sshd_config放开注释 公钥的位置修改 关闭密码登录 PubkeyAuthentication yes AuthorizedKeysFile .ssh/id_rsa.pub PasswordAuthentication no3. 下载id_rsa私钥, 自行解决 注意…

selenium爬取boss直聘招聘岗位数据

selenium爬取boss直聘招聘岗位数据 一、爬取流程二、完整代码一、爬取流程 先来看一下爬取到的数据情况: 再来看一下boss直聘的页面,这时需要我们已经完成了城市的选择,将岗位名称输入到搜索框中,点击搜索之后切换到第2页。这时我们将url复制。第2页的url为:https://www.…

Mybatis 系列全解(2)——全网免费最细最全,手把手教,学完就可做项目!

Mybatis 系列全解&#xff08;2&#xff09; 1. ResultMap结果集映射2. 日志2.1 日志工厂2.2 log4j 3. 分页3.1 实现SQL分页3.2 RowBounds 分页3.3 分页插件 4. 使用注解开发4.1 面向接口编程4.2 使用注解4.3 Mybatis 详细执行过程4.4 CRUD 增删改查 5. Lombok 1. ResultMap结果…

2-17 基于matlab的改进的遗传算法(IGA)对城市交通信号优化分析

基于matlab的改进的遗传算法&#xff08;IGA&#xff09;对城市交通信号优化分析。根据交通流量以及饱和流量&#xff0c;对城市道路交叉口交通信号灯实施合理优化控制&#xff0c;考虑到交通状况的动态变化&#xff0c;及每个交叉口的唯一性。通过实时监测交通流量&#xff0c…

【Text2SQL 论文】MCS-SQL:利用多样 prompts + 多项选择来做 Text2SQL

论文&#xff1a;MCS-SQL: Leveraging Multiple Prompts and Multiple-Choice Selection For Text-to-SQL Generation ⭐⭐⭐ arXiv:2405.07467 一、论文速读 已有研究指出&#xff0c;在使用 LLM 使用 ICL 时&#xff0c;ICL 的 few-shot exemplars 的内容、呈现顺序都会敏感…

设备智能化:中国星坤线缆组件的解决方案!

在当今快速发展的电子行业中&#xff0c;产品小型化和成本效益是制造商追求的两大目标。中国星坤端子电缆组件以其灵活性和高效性&#xff0c;为电子设备制造商提供了一种理想的解决方案。本文将探讨星坤端子电缆组件的优势以及其在不同电子设备中的应用。 端子线&#xff1a;小…

Dxf库中的DL_Attributes类

DL_Attributes 通常是 DXF 库中用于存储图形实体属性的类。在 DXF 文件中&#xff0c;每个图形实体都可以具有一系列属性&#xff0c;如颜色、线型、线宽等。DL_Attributes 类用于封装和管理这些属性&#xff0c;以便在创建、编辑和显示图形实体时使用。 以下是一个简单的伪代…

对于“青少年与成年人抑郁症的不同点”,以下说法错误的是?

对于“青少年与成年人抑郁症的不同点”&#xff0c;以下说法错误的是()点击查看答案 A.刻意引人关注B.易激惹或愤怒情绪 C.无法解释的隐痛或疼痛D.对于批评的极端敏感 青春期孩子的心理需求层次的是:①满足②成长③归属④需求 A.②③④ B.①③④C.③④② D.①②③ 关于亲子关系…

python之闭包以及服务器的开发

闭包&#xff1a; 函数嵌套函数 函数的返回值是一个函数 内部函数使用了外部函数的变量 造成数据不会被释放。 函数的参数是一个变量 def f(a):def f1():print(a)return f1f2 f(2) f2() # 2 函数的参数是另外一个函数 def fn(f):def fn1():f()return fn1def a():print(1…

autossh实现内外网穿透

一、介绍 ​ Autossh 是一个用于建立和维护 SSH 隧道的工具&#xff0c;它在网络连接断开或中断时可以自动重新连接。通过 Autossh&#xff0c;您可以方便地在不稳定的网络环境下保持持久的 SSH 连接。 ​ Autossh 是一个跨平台的工具&#xff0c;可在多个操作系统上使用&…

Java操作Redis(通过Jedis)

一、环境搭建 这里我使用的SpringBoot版本是2.6.3&#xff0c;所以我引入的Jedis相关版本也不是很高 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version></dependency><…

数学建模--Matlab求解线性规划问题两种类型实际应用

1.约束条件的符号一致 &#xff08;1&#xff09;约束条件的符号一致的意思就是指的是这个约束条件里面的&#xff0c;像这个下面的实例里面的三个约束条件&#xff0c;都是小于号&#xff0c;这个我称之为约束条件符号一致&#xff1b; &#xff08;2&#xff09;下面的就是上…

我的3次软考高项通关之旅

1、缘起 初次听说软考是在2022年下半年了&#xff0c;软考的高级分为很多种&#xff0c;我起先想报考高级架构师&#xff0c;但是架构师一年才考一次&#xff0c;如果一次考不过得再准备一年&#xff0c;时间对我来说太长了&#xff0c;于是我决定报考一年考两次的高项。对于国…