ClickHouse表引擎详解看这篇就够了-基本讲解、处理逻辑、测试实例

表引擎是ClickHouse设计实现中的一大特色。

表引擎在 ClickHouse 中的作用十分关键,直接决定了数据如何存储和读取、是否支持并发读写、是否支持 index、支持的 query 种类、是否支持主备复制等。

1、表引擎概述

1.1 介绍

ClickHouse 提供了大约 28 种表引擎,各有各的用途,比如有 Log 系列用来做小表数据分析,MergeTree 系列用来做大数据量分析,而 Integration 系列则多用于外表数据集成。再考虑复制表Replicated 系列,分布式表 Distributed 等,纷繁复杂,新用户上手选择时常常感到迷惑。

ClickHouse表引擎一共分为四个系列,分别是Log、MergeTree、Integration、Special。其中包含了两种特殊的表引擎Replicated、Distributed,功能上与其他表引擎正交,根据场景组合使用。

最强大的表引擎当属 MergeTree (合并树)引擎及该系列(*MergeTree)中的其他引擎。对于大多数正式的任务,推荐使用MergeTree 族中的引擎。因为只有合并树系列的表引擎才支持主键索引、数据分区、数据副本和数据采样这些特性,同时也只有此系列的表引擎支持ALTER相关操作。

Log、Special、Integration 主要用于特殊用途,场景相对有限。MergeTree 系列才是官方主推的存储引擎,支持几乎所有 ClickHouse 核心功能。

1.2 表引擎概览

一共分为四个系列,分别是Log、MergeTree、Integration、Special。其中包含了两种特殊的表引擎Replicated、Distributed,功能上与其他表引擎正交。

表引擎(即表的类型)决定了:

(1)数据的存储方式和位置,写到哪里以及从哪里读取数据

(2)支持哪些查询以及如何支持。

(3)并发数据访问。

(4)索引的使用(如果存在)。

(5)是否可以执行多线程请求。

(6)数据复制参数。

ClickHouse 的表引擎有很多,下面介绍其中几种,对其他引擎有兴趣的可以去查阅官方文档:https://clickhouse.yandex/docs/zh/operations/table_engines/

2、Ordinary默认数据库引擎

Ordinary就是ClickHouse中默认引擎,如果不指定数据库引擎创建的就是Ordinary数据库引擎,在这种数据库下面可以使用任意表引擎。

3、Log系列表引擎

Log系列表引擎功能相对简单,主要用于快速写入小表(1百万行左右的表),然后全部读出的场景。当你需要快速写入许多小表(最多约100万行)并在以后整体读取它们时,该类型的引擎是最有效的。

几种Log表引擎的共性是:

1、数据被顺序append写到磁盘上;

2、不支持delete、update修改数据;

3、不支持index;

4、不支持原子性写;如果某些操作(异常的服务器关闭)中断了写操作,则可能会获得带有损坏数据的表。

5、insert会阻塞select操作。当向表中写入数据时,针对这张表的查询会被阻塞,直至写入动作结束。

该类型的引擎有:

1、TinyLog

2、StripeLog

3、Log

3.1 TinyLog

TinyLog是Log系列引擎中功能简单、性能较低的引擎。

  • 它的存储结构由数据文件和元数据两部分组成。其中,数据文件是按列独立存储的,也就是说每一个列字段都对应一个文件。

  • 由于TinyLog数据存储不分块,所以不支持并发数据读取,该引擎适合一次写入,多次读取的场景,对于处理小批量中间表的数据可以使用该引擎,这种引擎会有大量小文件,性能会低。

  • 不支持索引

  • 该引擎没有并发控制:

  • 如果同时从表中读取和写入数据,则读取操作将抛出异常;

  • 如果同时写入多个查询中的表,则数据将被破坏。

  • Log 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。

示例:

-- 在ch中创建库 newdb,并使用

create database newdb;

use newdb;

-- 创建表t_tinylog 表,使用TinyLog引擎

create table t_tinylog(

id UInt8

,name String

,age UInt8

) engine=TinyLog;

-- 向表中插入数据

insert into t_tinylog values (1,'张三',18),(2,'李四',19),(3,'王五',20);

-- 查询表中的数据

select * from t_tinylog;

┌─id─┬─name─┬─age─┐

│ 1 │ 张三 │ 18 │

│ 2 │ 李四 │ 19 │

│ 3 │ 王五 │ 20 │

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

  • 不能删除数据

-- 在表中删除一条数据,这里是不支持delete。

delete from t_tinylog where id = 1;//语句不适合CH

alter table t_tinylog delete where id = 1;

:Exception: Mutations are not supported by storage TinyLog.

3.2 StripeLog

相比TinyLog而言,StripeLog数据存储会划分块,每次插入对应一个数据块,拥有更高的查询性能(拥有.mrk标记文件,支持并行查询)。

StripeLog 引擎将所有列存储在一个文件中,使用了更少的文件描述符。对每一次 Insert 请求,ClickHouse 将数据块追加在表文件的末尾,逐列写入。

StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。

-- 在库 newdb中创建表 t_stripelog,使用StripeLog引擎

create table t_stripelog(

id UInt8

,name String

,age UInt8

) engine = StripeLog;

#向表t_stripelog中插入数据,这里插入分多次插入,会将数据插入不同的数据块中

node1 :) insert into t_stripelog values (1,'张三',18);

node1 :) insert into t_stripelog values (2,'李四',19);

#查询表 t_stripelog数据

node1 :) select * from t_stripelog;

SELECT *

FROM t_stripelog

┌─id─┬─name─┬─age─┐

│ 1 │ 张三 │ 18 │

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

┌─id─┬─name─┬─age─┐

│ 2 │ 李四 │ 19 │

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

2 rows in set. Elapsed: 0.003 sec.

3.3 Log

Log引擎表适用于临时数据,一次性写入、测试场景。Log引擎结合了TinyLog表引擎和StripeLog表引擎的长处,是Log系列引擎中性能最高的表引擎。

Log表引擎会将每一列都存在一个文件中,对于每一次的INSERT操作,会生成数据块,经测试,数据块个数与当前节点的core数一致。

-- 在newdb中创建表t_log 使用Log表引擎

create table t_log(id UInt8 ,name String ,age UInt8 ) engine = Log;

-- 向表 t_log中插入数据,分多次插入,插入后数据存入数据块

insert into t_log values (1,'张三',18);

insert into t_log values (2,'李四',19);

insert into t_log values (3,'王五',20);

insert into t_log values (4,'马六',21);

insert into t_log values (5,'田七',22);

-- 查询表t_log中的数据

select * from t_log;

┌─id─┬─name─┬─age─┐

│ 1 │ 张三 │ 18 │

│ 2 │ 李四 │ 19 │

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

┌─id─┬─name─┬─age─┐

│ 3 │ 王五 │ 20 │

│ 4 │ 马六 │ 21 │

│ 5 │ 田七 │ 22 │

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

4、Special系列表引擎

4.1 Memory

Memory表引擎直接将数据保存在内存中,ClickHouse中的Memory表引擎具有以下特点:

  • Memory 引擎以未压缩的形式将数据存储在 RAM 中,数据完全以读取时获得的形式存储。

  • 并发数据访问是同步的,锁范围小,读写操作不会相互阻塞。

  • 不支持索引。

  • 查询是并行化的,在简单查询上达到最大速率(超过10 GB /秒),在相对较少的行(最多约100,000,000)上有高性能的查询。

  • 没有磁盘读取,不需要解压缩或反序列化数据,速度更快(在许多情况下,与 MergeTree 引擎的性能几乎一样高)。

  • 重新启动服务器时,表存在,但是表中数据全部清空。

  • Memory引擎多用于测试。

示例:

  • 重启clickhouse服务,Memory表存在,但数据丢失

-- 在 newdb中创建表 t_memory ,表引擎使用Memory

CREATE TABLE t_memory

(

`id` UInt8,

`name` String,

`age` UInt8

)

ENGINE = Memory

-- 向表 t_memory中插入数据

insert into t_memory values (1,'张三',18),(2,'李四',19),(3,'王五',20);

-- 查询表t_memory中的数据

select * from t_memory;

┌─id─┬─name─┬─age─┐

│ 1 │ 张三 │ 18 │

│ 2 │ 李四 │ 19 │

│ 3 │ 王五 │ 20 │

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

-- 重启clickhouse 服务

service clickhouse-server restart

-- 进入 newdb 库,查看表 t_memory数据,数据为空。

select * from t_memory;

4.2 Merge

Merge 引擎 (不要跟 MergeTree 引擎混淆) 本身不存储数据,但可用于同时从任意多个其他的表中读取数据,这里需要多个表的结构相同,并且创建的Merge引擎表的结构也需要和这些表结构相同才能读取。

读是自动并行的,不支持写入。读取时,那些被真正读取到数据的表如果设置了索引,索引也会被使用。

示例:

  • merge表引擎根据正则查询表名,聚合相同表结构的数据

-- 1、创建3张表,表结构相同,并插入数据

-- 在newdb库中创建表m_t1,并插入数据

create table m_t1 (

id UInt8 ,name String,age UInt8

) engine = TinyLog;

insert into m_t1 values (1,'张三',18),(2,'李四',19)

-- 在newdb库中创建表m_t2,并插入数据

create table m_t2 (

id UInt8 ,name String,age UInt8

) engine = TinyLog;

insert into m_t2 values (3,'王五',20),(4,'马六',21)

-- 在newdb库中创建表m_t3,并插入数据

create table m_t3 (

id UInt8 ,name String,age UInt8

) engine = TinyLog;

insert into m_t3 values (5,'田七',22),(6,'赵八',23)

-- 2、在newdb库中创建表t_merge,使用Merge引擎,匹配m开头的表

create table t_merge (

id UInt8,name String,age UInt8

) engine = Merge(newdb,'^m');

-- 查询 t_merge表中的数据

select * from t_merge;

┌─id─┬─name──┬─age─┐

│ 1 │ 张三 │ 18 │

│ 2 │ 李四 │ 19 │

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

┌─id─┬─name─┬─age─┐

│ 3 │ 王五 │ 20 │

│ 4 │ 马六 │ 21 │

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

┌─id─┬─name─┬─age─┐

│ 5 │ 田七 │ 22 │

│ 6 │ 赵八 │ 23 │

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

4.3 Distributed

Distributed是ClickHouse中分布式引擎,使用分布式引擎声明的表才可以在其他节点访问与操作。

Distributed引擎和Merge引擎类似,本身不存放数据,功能是在不同的server上把多张相同结构的物理表合并为一张逻辑表。

1> 语法

Distributed(cluster_name, database_name, table_name[, sharding_key])

对以上语法解释:

  • cluster_name:集群名称,与集群配置中的自定义名称相对应。配置在/etc/clickhouse-server/config.d/metrika.xml文件中,如下图:

  • database_name:数据库名称。

  • table_name:表名称。

  • sharding_key:可选的,用于分片的key值,在数据写入的过程中,分布式表会依据分片key的规则,将数据分布到各个节点的本地表。

注意:创建分布式表是读时检查的机制,也就是说对创建分布式表和本地表的顺序并没有强制要求。

2> 示例

-- 1、在node1、node2、node3节点上启动ClickHouse 服务

-- 2、使用默认的default库,在每个节点上创建表 test_table

node1 :) create table test_local (id UInt8,name String) engine= TinyLog

node2 :) create table test_local (id UInt8,name String) engine= TinyLog

node3 :) create table test_local (id UInt8,name String) engine= TinyLog

-- 3、在node1上创建分布式表 t_distributed,表引擎使用 Distributed 引擎

node1 :) create table t_distributed(id UInt8,name String) engine = Distributed(ckcluster,default,test_local,id);

-- 注意:以上分布式表 t_distributed 只存在与node1节点的clickhouse中。

-- 4、分别在node1、node2、node3节点上向表test_local中插入2条数据

node1 :) insert into test_local values (1,'张三'),(2,'李四');

node2 :) insert into test_local values (3,'王五'),(4,'马六');

node3 :) insert into test_local values (5,'田七'),(6,'赵八');

-- 5、查询分布式表 t_distributed 中的数据

node1 :) select * from t_distributed;

┌─id─┬─name──┐

│ 1 │ 张三 │

│ 2 │ 李四 │

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

┌─id─┬─name─┐

│ 5 │ 田七 │

│ 6 │ 赵八 │

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

┌─id─┬─name─┐

│ 3 │ 王五 │

│ 4 │ 马六 │

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

-- 6、向分布式表 t_distributed 中插入一些数据,然后查询 node1、node2、node3节点上的test_local数据,发现数据已经分布式存储在不同节点上

node1 :) insert into t_distributed values (7,'zs'),(8,'ls'),(9,'ww'),(10,'ml'),(11,'tq'),(12,'zb');

-- node1查询本地表 test_local

node1 :) select * from test_local;

┌─id─┬─name─┐

│ 1 │ 张三 │

│ 2 │ 李四 │

│ 9 │ ww │

│ 12 │ zb │

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

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值