MySQL
的数据表有
InnoDB
和
MyISAM
存储引擎,不同的存储引擎提供不同的存储机
制、索引方式等功能,也可以称之为表类型。在
ClickHouse
中也有表引擎。
表引擎在
ClickHouse
中的作用十分关键,直接决定了
数据如何存储和读取、是否支
持并发读写、是否支持
index
索引、支持的
query
种类、是否支持主备复制
等。
ClickHouse
提供了大约
28
种表引擎,各有各的用途,比如有
Log
系列用来做小表
数据分析,
MergeTree
系列用来做大数据量分析,而
Integration
系列则多用于外表数
据集成。再考虑复制表
Replicated
系列,分布式表
Distributed
等
ClickHouse
表引擎一共分为四个系列,分别是
Log 系列、MergeTree 系列、Integration 系列、Special 系列。其中包含了两种特殊的表引擎 Replicated、Distributed,功能上与其他表引擎正交,根据场景组合使用。
Log系列表引擎
Log
系列表引擎功能相对简单,主要用于快速写入小表(
1
百万行左右的表),然后全
部读出的场景,即一次写入,多次查询。
Log
系列表引擎包含:
TinyLog
、
StripeLog
、
Log
三种引擎。
几种
Log
表引擎的共性是:
数据被顺序
append
写到本地磁盘上。
不支持
delete
、
update
修改数据。
不支持
index
(索引)。
不支持原子性写。如果某些操作
(
异常的服务器关闭
)
中断了写操作,则可能会获
得带有损坏数据的表。
insert
会阻塞
select
操作。当向表中写入数据时,针对这张表的查询会被阻塞,
直至写入动作结束。
它们彼此之间的区别是:
TinyLog
:不支持并发读取数据文件,查询性能较差;格式简单,适合用来暂存
中间数据。
StripLog
:支持并发读取数据文件,查询性能比
TinyLog
好;将所有列存储在
同一个大文件中,减少了文件个数。
Log
:支持并发读取数据文件,查询性能比
TinyLog
好;每个列会单独存储在一
个独立文件中
TinyLog
TinyLog
是
Log
系列引擎中功能简单、性能较低的引擎。
它的存储结构由数据文件和元数据两部分组成。其中,数据文件是按列独立存储的,也
就是说每一个列字段都对应一个文件。 由于
TinyLog
数据存储不分块
,所以不支持并发数据读取,该引擎适合一次写入,多
次读取的场景,对于处理小批量中间表的数据可以使用该引擎,这种引擎会有大量小文件,
性能会低
create table t_tinylog(id UInt8,name String,age UInt8)
engine=TinyLog;
insert into t_tinylog values (1,'
张三
',18),(2,'
李四
',19),(3,'
王五
',20);
#
在表中删除一条数据,这里是不支持
delete
。
alter table t_tinylog delete where id = 1;
当 在
newdb
库 中 创 建 表
t_tinylog
后 , 在
ClickHouse 保 存 数 据 的 目 录 /var/lib/clickhouse/data/newdb/
下会多一个
t_tinylog
目录在向表 t_tinylog 中插入数据后,进入“
t_tinylog”目录,查看目录下的文件, 如下图所示:
![](https://img-blog.csdnimg.cn/3f3b710a93d04f328e50f2165da90704.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Ziz5YWJLeaYn-i-sOWkp-a1tw==,size_20,color_FFFFFF,t_70,g_se,x_16)
表
t_tinylog
中的每个列都单独对应一个
*.bin 文件,同时还有一 个
sizes.json
文件存储元数据,记录了每个
bin
文件中数据大小
StripeLog
StripeLog
数据存储会划分块,每次插入对应一个数据块
,拥
有更高的查询性能(拥有
.mrk
标记文件,支持并行查询)。
StripeLog
引擎将所有列存
储在一个文件中,使用了更少的文件描述符。对每一次
Insert
请求,
ClickHouse
将
数据块追加在表文件的末尾,逐列写入。
StripeLog
引擎不支持
ALTER UPDATE
和
ALTER DELETE
操作。
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);
当 在
newdb
库 中创 建表
t_stripelog
后 ,在
ClickHouse 保 存数 据的 目录 /var/lib/clickhouse/data/newdb/
下会多一个
t_stripelog
目录,如图所示:
![](https://img-blog.csdnimg.cn/c476cce7af604c4a88a42b9ca5c289e9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Ziz5YWJLeaYn-i-sOWkp-a1tw==,size_20,color_FFFFFF,t_70,g_se,x_16)
data.bin:
数据文件,所有列字段都写入
data.bin
文件中。
index.mrk:
数据标记文件,保存了数据在
data.bin
文件中的位置信息,即每
个插入数据列的
offset
信息,利用数据标记能够使用多个线程,并行度取
data.bin
压缩数据,提升查询性能。
sizes.json:
元数据文件,记录了
data.bin
和
index.mrk
大小信息。
Log
Log
引擎表适用于临时数据,一次性写入、测试场景。
Log
引擎结合了
TinyLog
表引
擎和
StripeLog
表引擎的长处,是
Log
系列引擎中性能最高的表引擎。
Log
表引擎会将每一列都存在一个文件中,
对于每一次的
INSERT
操作,会生成数据
块
,经测试,
数据块个数与当前节点的
core
数一致。
create table t_log(id UInt8 ,name String ,age UInt8 ) engine
= Log;
#
向表
t_log
中插入数据,分多次插入,插入后数据存入数据块
node1 :)
insert into t_log values (1,'
张三
',18);
node1 :)
insert into t_log values (2,'
李四
',19);
node1 :)
insert into t_log values (3,'
王五
',20);
node1 :)
insert into t_log values (4,'
马六
',21);
node1 :)
insert into t_log values (5,'
田七
',22);
当 在
newdb
库 中 创 建 表
t_log
后 , 在
ClickHouse
保 存 数 据 的 目 录
/var/lib/clickhouse/data/newdb/
下会多一个
t_log
目录,如图所示:
![](https://img-blog.csdnimg.cn/49beb9a2504b4582bacc34a25a7e75a1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Ziz5YWJLeaYn-i-sOWkp-a1tw==,size_20,color_FFFFFF,t_70,g_se,x_16)
我们发现表
t_log
中的每个列都对应一个
*.bin
文件。其他两个文件的解释如下:
__marks.mrk
:数据标记,保存了每个列文件中的数据位置信息,利用数据标记
能够使用多个线程,并行度取
data.bin
压缩数据,提升查询性能。
sizes.json:
记录了
*.bin
和
__mark.mrk
大小的信息。
Special系列引擎
Memory
表引擎直接将数据保存在内存中,
ClickHouse
中的
Memory
表引擎具有以
下特点
:
Memory
引擎以未压缩的形式将数据存储在
RAM
中,数据完全以读取时获得的形
式存储。
并发数据访问是同步的,锁范围小,读写操作不会相互阻塞。
不支持索引。
查询是并行化的,在简单查询上达到最大速率(超过
10 GB /
秒),在相对较少
的行(最多约
100,000,000
)上有高性能的查询。
没有磁盘读取,不需要解压缩或反序列化数据,速度更快(在许多情况下,与
MergeTree
引擎的性能几乎一样高)。
重新启动服务器时,表存在,但是表中数据全部清空。
Memory
引擎多用于测试。
create table t_memory(id UInt8 ,name String, age UInt8) engine
= Memory;
注意:
”Memory”
表引擎写法固定,不能小写。同时创建好表
t_memory
后,在对应
的磁盘目录
/var/lib/clickhouse/data/newdb
下没有“
t_memory
”目录,基于内存
存储,当重启
ClickHouse
服务后,表
t_memory
存在,但是表中数据全部清空。
Merge
Merge
引擎
(
不要跟
MergeTree
引擎混淆
)
本身不存储数据,但可用于同时从任
意多个其他的表中读取数据,这里需要多个表的结构相同,并且创建的
Merge
引擎表的结
构也需要和这些表结构相同才能读取。 读是自动并行的,不支持写入。读取时,那些被真正读取到数据的表如果设置了索引, 索引也会被使用。
Merge
引擎的参数:一个数据库名和一个用于匹配表名的正则表达式:
Merge(
数据库
,
正则表达式
)
例如:
Merge(hits, '^WatchLog')
表示数据会从
hits
数据库中表名匹配正则
‘
^WatchLog
’ 的表中读取。
注意
:
当选择需要读取的表时,会匹配正则表达式匹配上的表,如果当前
Merge
表的
名称也符合正则表达式匹配表名,这个
Merge
表本身会自动排除,以避免进入递归死循环,
当然也可以创建两个相互无限递归读取对方数据的
Merge
表,但这并没有什么意义。
例子:
create table m_t1 (id UInt8 ,name String,age UInt8) engine
= TinyLog;
node1 :)
insert into m_t1 values (1,'
张三
',18),(2,'
李四
',19)
#
在
newdb
库中创建表
m_t2
,并插入数据
node1 :)
create table m_t2 (id UInt8 ,name String,age UInt8) engine
= TinyLog;
node1 :)
insert into m_t2 values (3,'
王五
',20),(4,'
马六
',21)
#
在
newdb
库中创建表
m_t3
,并插入数据
node1 :)
create table m_t3 (id UInt8 ,name String,age UInt8) engine
= TinyLog;
node1 :)
insert into m_t3 values (5,'
田七
',22),(6,'
赵八
',23)
#
在
newdb
库中创建表
t_merge
,使用
Merge
引擎,匹配 <