首页 > 其他分享 >详解 ClickHouse 的表引擎

详解 ClickHouse 的表引擎

时间:2024-06-20 18:31:17浏览次数:22  
标签:sku 00 06 -- 引擎 2020 ClickHouse order 详解

一、简介

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

二、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_0
    	detached #卸载目录
    	format_version.txt #版本文件
    
    #分区目录名组成:分区值_最小分区块编号_最大分区块编号_合并层级
    	#分区值:分区值由 partition by 指定的分区字段决定
    		#未指定分区字段:分区值为 all
    		#整型的分区字段:以该字段整型值的字符串形式作为分区值
    		#日期型或可转成日期的分区字段:以该字段值的字符串形式作为分区值
    		#String、Float等类型的分区字段:通过128位的Hash算法取字段的Hash值作为分区值
    	#最小分区块编号:自增,从1开始向上递增,每产生一个分区目录就向上递增一个数字
    	#最大分区块编号:新创建的分区的最大分区块编号=最小分区块编号
    	#合并层级:被合并的次数
    
    #分区目录文件:
    20200601_1_1_0
    	checksums.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
    

标签:sku,00,06,--,引擎,2020,ClickHouse,order,详解
From: https://blog.csdn.net/weixin_44480009/article/details/139840030

相关文章

  • MoneyPrinterPlus:AI自动短视频生成工具-阿里云配置详解
    MoneyPrinterPlus是一个很好的自动短视频生成工具,虽然是一个非常好的工具,但是有些小伙伴可能不太清楚具体应该如何配置才能让它跑起来。因为MoneyPrinterPlus依赖一些具体的配置信息,所以还是很有必要给大家讲解清楚如何进行配置。项目已开源,代码地址:https://github.com/ddean200......
  • TCP与UDP详解:层次、区别及应用场景
    TCP和UDP的层次及区别详解所属层次TCP(TransmissionControlProtocol,传输控制协议)和UDP(UserDatagramProtocol,用户数据报协议)都属于OSI模型中的传输层(第四层)。在传输层,协议的主要作用是为端到端的通信提供逻辑通信,并确保数据在网络上传输的可靠性和顺序。TCP和UDP的区别......
  • 【数据结构与算法】二叉树的性质 详解
    在二叉树的第i层上至多有多少个结点。在二叉树的第i层上至多有2i−1......
  • 【数据结构与算法】树,二叉树 详解
    给出树的不同的几种表示形式。邻接矩阵:这是一种二维数组,其中的元素表示两个节点之间是否存在边。这种表示形式适用于稠密图,但对于稀疏图可能会浪费很多空间。邻接表:这是一种数组和链表的组合结构。数组的每个元素都是一个链表,链表中的元素表示与该节点相连的其他节点。这种......
  • 详解Web应用安全系列(1)注入漏洞之SQL注入
    注入漏洞通常是指在可输入参数的地方,通过构造恶意代码,进而威胁应用安全和数据库安全。常见的注入漏洞包括:SQL注入和XSS跨站脚本攻击。这篇文章我们主要讲SQL注入,SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查......
  • Python 基础详解:入门宝典(3)
    容器类型介绍:1.列表(List)列表是Python中最常用的数据结构之一,它是一个有序的可变序列,允许存储任意类型的元素。列表用方括号[]表示。特点有序:元素按照插入顺序排列。可变:可以修改元素的值或增加、删除元素。支持重复:可以包含重复的元素。#创建一个列表fruits=['a......
  • 只狼风灵月影修改器操作详解:提升游戏体验的全面教程
     《只狼:影逝二度》是一款由FromSoftware开发,动视发行的动作冒险游戏,设定在日本战国时代,玩家扮演一名忍者,面对残酷的战斗与挑战,在死亡与重生的循环中,拯救被绑架的领主,揭示背后的神秘故事。以其高强度的战斗系统、精妙的关卡设计和深刻的叙事而著称,强调精准时机的格挡与反击机制......
  • 详解Kubernetes Pod优雅退出
    1、概述Pod优雅关闭是指在Kubernetes中,当Pod因为某种原因(如版本更新、资源不足、故障等)需要被终止时,Kubernetes不会立即强制关闭Pod,而是首先尝试以一种“优雅”的方式关闭Pod。这个过程允许Pod中的容器有足够的时间来响应终止信号(默认为SIGTERM),并在终止前完成必要的清理工作,......
  • Docker配置与使用详解
    一、引言随着云计算和微服务的兴起,Docker作为一种轻量级的容器化技术,越来越受到开发者和运维人员的青睐。Docker通过容器化的方式,将应用程序及其依赖项打包成一个可移植的镜像,从而实现了应用程序的快速部署和扩展。本文将详细介绍Docker的配置与使用,包括Docker的安装、镜像......
  • 【windows|007】DHCP服务详解
    ......