ClickHouse表引擎(一)之MergeTree系列

本文将介绍ClickHouse中一个非常重要的概念—表引擎(table engine)。如果对MySQL熟悉的话,或许你应该听说过InnoDB和MyISAM存储引擎。那不同的存储引擎提供着不同的存储机制、索引方式、锁定水平等功能,也可以称之为表类型。

对于ClickHouse 的表引擎提供了四个系列(MergeTree、Log、Integration、Special)大约 28 种表引擎,各有各的用途。比如 MergeTree 系列用来做大数据量分析,Log 系列用来做小表数据分析,而 Integration 系列则多用于外表数据集成。Log、Special、Integration 系列的表引擎相对来说,应用场景有限,功能简单,应用特殊用途,MergeTree 系列表引擎又和两种特殊表引擎(Replicated,Distributed)正交形成多种具备不同功能的 MergeTree 表 引擎,今天我们主要介绍MergeTree系列的引擎。

这是 ClickHouse 的表引擎系列家谱:
在这里插入图片描述

1.MergeTree

关于MergeTree引擎的基础请点击:Clickhouse基础
关于MergeTree引擎的WAL请点击:新功能Write-Ahead-Log
关于MergeTree引擎的MySQL同步请点击:ClickHouse王炸功能来袭之同步Binlog
关于MergeTree引擎的TTL请点击:MergeTree系列表引擎之TTL
关于MergeTree引擎的多卷存储请点击:ClickHouse多卷存储策略

2.ReplacingMergeTree

MergeTree拥有主键,但是主键没有唯一键约束(会出现主键相同)。

ReplacingMergeTree为了数据去重而设计,能够在合并分区时删除重复的数据。一定程度解决了重复数据的问题(同分区数据去重)。

# 建表语法
CREATE TABLE replace_table(
    id String,
    code String,
    create_time DateTime
) ENGINE = ReplacingMergeTree()
partition by toYYYYMM(create_time)
ORDER BY(id,code)
PRIMARY KEY id ;

insert into replace_table values('A001','C1','2021-03-10 17:00:00'),('A001','C1','2021-03-12 17:00:00'),('A001','C100','2021-03-13 17:00:00'),('A001','C200','2021-03-14 17:00:00'),('A002','C2','2021-03-15 17:00:00'),('A003','C3','2021-03-16 17:00:00');

select * from replace_table;

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-10 17:00:00 │
│ A001 │ C1   │ 2021-03-12 17:00:00 │
│ A001 │ C100 │ 2021-03-13 17:00:00 │
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────┘

ORDER BY是去除重复数据的关键,排序键ORDER BY所声明的表达式是后续作为判断数据是否重复的依据。在这个例子中,数据会基于id和code两个字段去重。

执行optimize强制触发合并后,会按照id和code分组,保留分组内的最后一条(观察create_time日期字段):

optimize TABLE replace_table FINAL;

select * from replace_table;

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-12 17:00:00 │
│ A001 │ C100 │ 2021-03-13 17:00:00 │
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────

从执行的结果来看,ReplacingMergeTree在去除重复数据时,确实是以ORDERBY排序键为基准的,而不是PRIMARY KEY。因为在上面的例子中,ORDER BY是(id, code),而PRIMARY KEY是id,如果按照id值去除重复数据,则最终结果应该只剩下A001、A002和A003三行数据。

CREATE TABLE replace_table_v1(
    id String,
    code String,
    create_time DateTime
) ENGINE = ReplacingMergeTree()
partition by toYYYYMM(create_time)
ORDER BY(id)
PRIMARY KEY id;

insert into replace_table values('A001','C1','2021-03-10 17:00:00'),('A001','C1','2021-03-12 17:00:00'),('A001','C100','2021-03-13 17:00:00'),('A001','C200','2021-03-14 17:00:00'),('A002','C2','2021-03-15 17:00:00'),('A003','C3','2021-03-16 17:00:00');

select * from replace_table_v1 ;
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-10 17:00:00 │
│ A001 │ C1   │ 2021-03-12 17:00:00 │
│ A001 │ C100 │ 2021-03-13 17:00:00 │
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────┘

optimize TABLE replace_table_v1 FINAL;
select * from replace_table_v1 ;
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────┘
写入之后,执行optimize强制分区合并,并查询数据:

insert into replace_table values ('A001','C1','2021-02-17 21:00:00');
select * from replace_table;
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-12 17:00:00 │
│ A001 │ C100 │ 2021-03-13 17:00:00 │
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────┘
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-02-17 21:00:00 │
└──────┴──────┴─────────────────────┘

optimize TABLE replace_table FINAL;
select * from replace_table;

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-02-17 21:00:00 │
└──────┴──────┴─────────────────────┘
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-12 17:00:00 │
│ A001 │ C100 │ 2021-03-13 17:00:00 │
│ A001 │ C200 │ 2021-03-14 17:00:00 │
│ A002 │ C2   │ 2021-03-15 17:00:00 │
│ A003 │ C3   │ 2021-03-16 17:00:00 │
└──────┴──────┴─────────────────────┘

观察返回的数据,可以看到A001:C1依然出现了重复。这是因为ReplacingMergeTree是以分区为单位删除重复数据的。只有在相同的数据分区内重复的数据才可以被删除,而不同数据分区之间的重复数据依然不能被剔除。这就是上面说ReplacingMergeTree只是在一定程度上解决了重复数据问题的原因。

ReplacingMergeTree版本号的用法。以下面的语句为例:

CREATE TABLE replace_table_v (
    id String,
    code String,
    create_time DateTime
) ENGINE = ReplacingMergeTree(create_time)
PARTITION  BY toYYYYMM(create_time)
ORDER BY id ;
	replace_table_v基于id字段去重,并且使用create_time字段作为版本号

insert into replace_table_v values('A001','C1','2019-05-10 17:00:00'),('A001','C1','2019-05-25 17:00:00'),('A001','C200','2019-05-13 17:00:00');

select * from replace_table_v

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-10 17:00:00 │
│ A001 │ C1   │ 2021-03-25 17:00:00 │
│ A001 │ C200 │ 2021-03-13 17:00:00 │
└──────┴──────┴─────────────────────┘

optimize TABLE replace_table_v FINAL;
select * from replace_table_v ;

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2021-03-25 17:00:00 │
└──────┴──────┴─────────────────────┘

ReplacingMergeTree的处理逻辑。

(1)使用ORBER BY排序键作为判断重复数据的唯一键。

(2)只有在合并分区的时候才会触发删除重复数据的逻辑。

(3)以数据分区为单位删除重复数据。当分区合并时,同一分区内的重复数据会被删除;不同分区之间的重复数据不会被删除。

(4)在进行数据去重时,因为分区内的数据已经基于ORBER BY进行了排序,所以能够找到那些相邻的重复数据。

(5)数据去重策略有两种:

如果没有设置ver版本号,则保留同一组重复数据中的最后一行。

如果设置了ver版本号,则保留同一组重复数据中ver字段取值最大的那一行。

3.SummingMergeTree

假设有这样一种查询需求:终端用户只需要查询数据的汇总结果,不关心明细数据,并且数据的汇总条件是预先明确的(GROUP BY条件明确,且不会随意改变)。对于这样的查询场景,在ClickHouse中如何解决呢?最直接的方案就是使用MergeTree存储数据,然后通过GROUP BY聚合查询,并利用SUM聚合函数汇总结果。这种方案存在两个问题。

存在额外的存储开销:终端用户不会查询任何明细数据,只关心汇总结果,所以不应该一直保存所有的明细数据。

存在额外的查询开销:终端用户只关心汇总结果,虽然MergeTree性能强大,但是每次查询都进行实时聚合计算也是一种性能消耗。

在MergeTree的每个数据分区内,数据会按照ORDER BY表达式排序。主键索引也会按照PRIMARY KEY表达式取值并排序。而ORDER BY可以指代主键,所以在一般情形下,只单独声明ORDER BY即可。也就是说此时,ORDER BY与PRIMARY KEY定义相同,数据排序与主键索引相同。

如果同时定义ORDER BY与PRIMARY KEY,那便是明确希望ORDER BY与PRIMARY KEY不同。这种情况通常只会在使用SummingMergeTree或AggregatingMergeTree时才会出现。这是因为SummingMergeTree与AggregatingMergeTree的聚合都是根据ORDER BY进行的。由此可以引出两点原因:主键与聚合的条件定义分离,为修改聚合条件留下空间。

现在用一个示例说明。假设一张SummingMergeTree数据表有A、B、C、D、E、F六个字段,如果需要按照A、B、C、D汇总,则有:

ORDER BY (A,B,C,D)

但是如此一来,此表的主键也被定义成了A、B、C、D。而在业务层面,其实只需要对字段A进行查询过滤,应该只使用A字段创建主键。所以,一种更加优雅的定义形式应该是:

ORDER BY (A,B,C,D) 
PRIMARY KEY A

如果同时声明了ORDER BY与PRIMARY KEY, MergeTree会强制要求PRIMARYKEY列字段必须是ORDER BY的前缀。例如下面的定义是错误的:

ORDER BY(B,C) 
PRIMARY KEY A
        

PRIMARY KEY必须是ORDER BY的前缀:

ORDER BY (B,C) 
PRIMARY KEY B

这种强制约束保障了即便在两者定义不同的情况下,主键仍然是排序键的前缀,不会出现索引与数据顺序混乱的问题。

假设现在业务发生了细微的变化,需要减少字段,将先前的A、B、C、D改为按照A、B聚合汇总,则可以按如下方式修改排序键:

ALTER TABLE table_name MODIFY ORDER BY (A,B)
-- 示例
CREATE TABLE summing_table(
    id String,
    city String,
    v1 UInt32,
    v2 Float64,
    create_time DateTime
) ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id,city)
PRIMARY KEY id ;


insert into summing_table values('A001','beijing',10,20,'2021-01-01 18:00:00');
insert into summing_table values('A001','beijing',30,10,'2021-01-10 18:00:00');
insert into summing_table values('A002','shanghai',20,15,'2021-03-10 18:00:00');
insert into summing_table values('A003','beijing',30,10,'2021-02-10 18:00:00');
insert into summing_table values('A001','beijing',5,5,'2021-03-10 18:00:00');

select * from summing_table;

┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A003 │ beijing │ 30102021-02-10 18:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city─────┬─v1─┬─v2─┬─────────create_time─┐
│ A001 │ beijing  │  552021-03-10 18:00:00 │
│ A002 │ shanghai │ 20152021-03-10 18:00:00 │
└──────┴──────────┴────┴────┴─────────────────────┘
┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A001 │ beijing │ 10202021-01-01 18:00:00 │
│ A001 │ beijing │ 30102021-01-10 18:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘

optimize table summing_table final;
select * from summing_table;

┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A003 │ beijing │ 30102021-02-10 18:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A001 │ beijing │ 40302021-01-01 18:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city─────┬─v1─┬─v2─┬─────────create_time─┐
│ A001 │ beijing  │  552021-03-10 18:00:00 │
│ A002 │ shanghai │ 20152021-03-10 18:00:00 │
└──────┴──────────┴────┴────┴─────────────────────┘

至此能够看到,在第一个分区内,同为A001:beijing的两条数据汇总成了一行。其中,v1和v2被SUM汇总,不在汇总字段之列的create_time则选取了同组内第一行数据的取值。而不同分区之间,数据没有被汇总合并。

SummingMergeTree的处理逻辑

(1)用ORBER BY排序键作为聚合数据的条件Key。

(2)只有在合并分区的时候才会触发汇总的逻辑。

(3)以数据分区为单位来聚合数据。当分区合并时,同一数据分区内聚合Key相同的数据会被合并汇总,而不同分区之间的数据则不会被汇总。

(4)如果在定义引擎时指定了columns汇总列(非主键的数值类型字段),则SUM汇总这些列字段;如果未指定,则聚合所有非主键的数值类型字段。

(5)在进行数据汇总时,因为分区内的数据已经基于ORBER BY排序,所以能够找到相邻且拥有相同聚合Key的数据。

(6)在汇总数据时,同一分区内,相同聚合Key的多行数据会合并成一行。其中,汇总字段会进行SUM计算;对于那些非汇总字段,则会使用第一行数据的取值。

(7)支持嵌套结构,但列字段名称必须以Map后缀结尾。嵌套类型中,默认以第一个字段作为聚合Key。除第一个字段以外,任何名称以Key、Id或Type为后缀结尾的字段,都将和第一个字段一起组成复合Key。

4.AggregatingMergeTree

AggregatingMergeTree更为常见的应用方式是结合物化视图使用,将它作为物化视图的表引擎。

–使用MergeTree作为底表,用于存储全量的明细数据,并以此对外提供实时查询。

CREATE TABLE agg_table_basic(
    id String,
    city String,
    code String,
    value UInt32
) ENGINE = MergeTree()
PARTITION BY city
ORDER BY(id,city);

-- 新建一张物化视图,物化视图使用AggregatingMergeTree表引擎,用于特定场景的数据查询
CREATE MATERIALIZED VIEW agg_view
ENGINE = AggregatingMergeTree()
PARTITION BY city
ORDER BY (id,city)
AS SELECT
id,city,
uniqState(code) AS code,
sumState(value) as value
FROM agg_table_basic
group by id,city;

--在新增数据时,面向的对象是底表MergeTree:
INSERT INTO TABLE agg_table_basic
VALUES('A000','wuhan','code1',100),
      ('A000','wuhan','code2',200),
      ('A000','zhuhai','code1',200) ;

数据会自动同步到物化视图,并按照AggregatingMergeTree引擎的规则处理。
在查询数据时,面向的对象是物化视图AggregatingMergeTree:

SELECT id,sumMerge(value),uniqMerge(code) FROM agg_view GROUP BY id,city ;

┌─id───┬─sumMerge(value)─┬─uniqMerge(code)─┐
│ A000 │             2001 │
│ A000 │             3002 │
└──────┴─────────────────┴─────────────────┘

AggregatingMergeTree的处理逻辑。

(1)用ORBER BY排序键作为聚合数据的条件Key。

(2)使用AggregateFunction字段类型定义聚合函数的类型以及聚合的字段。(3)只有在合并分区的时候才会触发聚合计算的逻辑。

(4)以数据分区为单位来聚合数据。当分区合并时,同一数据分区内聚合Key相同的数据会被合并计算,而不同分区之间的数据则不会被计算。

(5)在进行数据计算时,因为分区内的数据已经基于ORBER BY排序,所以能够找到那些相邻且拥有相同聚合Key的数据。

(6)在聚合数据时,同一分区内,相同聚合Key的多行数据会合并成一行。对于那些非主键、非AggregateFunction类型字段,则会使用第一行数据的取值。

(7)AggregatingMergeTree通常作为物化视图的表引擎,与普通MergeTree搭配使用。

5.CollapsingMergeTree

数据库中数据实现行级粒度的修改或删除,最符合常理的思维可能是:首先找到保存数据的文件,接着打开这个文件,删除或者修改那些需要变化的数据行。相较于直接修改源文件,ClickHouse会将修改和删除操作转换成新增操作,即以增代删。

CollapsingMergeTree就是一种通过以增代删的思路,支持行级数据修改和删除的表引擎。它通过定义一个sign标记位字段,记录数据行的状态。如果sign标记为1,则表示这是一行有效的数据;如果sign标记为-1,则表示这行数据需要被删除。当CollapsingMergeTree分区合并时,同一数据分区内,sign标记为1和-1的一组数据会被抵消删除。

删除数据示例
CREATE TABLE collpase_table(
    id String,
    code Int32,
    create_time DateTime,
    sign Int8
) ENGINE = CollapsingMergeTree(sign)
PARTITION BY toYYYYMM(create_time)
ORDER BY id ;


INSERT INTO TABLE collpase_table VALUES('A000',100,now(),1);
INSERT INTO TABLE collpase_table VALUES('A000',100,now(),-1);           镜像数据(order by字段必须和源数据相同)
INSERT INTO TABLE collpase_table VALUES('A000',200,now(),1);
select * from collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  1002021-03-11 16:19:01-1 │
└──────┴──────┴─────────────────────┴──────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  1002021-03-11 16:18:521 │
└──────┴──────┴─────────────────────┴──────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  2002021-03-11 16:19:171 │
└──────┴──────┴─────────────────────┴──────┘


optimize table collpase_table;
select * from collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  2002021-03-11 16:19:171 │
└──────┴──────┴─────────────────────┴──────┘

INSERT INTO TABLE collpase_table VALUES('A000',500,now(),1);
INSERT INTO TABLE collpase_table VALUES('A000',500,now(),-1);           镜像数据(order by字段必须和源数据相同)
select * from collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  5002021-03-11 16:23:521 │
└──────┴──────┴─────────────────────┴──────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  5002021-03-11 16:23:57-1 │
└──────┴──────┴─────────────────────┴──────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  2002021-03-11 16:19:171 │
└──────┴──────┴─────────────────────┴──────┘


optimize table collpase_table;
select * from collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┐
│ A000 │  5002021-03-11 16:23:521 │
└──────┴──────┴─────────────────────┴──────┘

CollapsingMergeTree在折叠数据时,遵循以下规则。

  1. 如果sign=1比sign=-1的数据多一行,则保留最后一行sign=1的数据。
  2. 如果sign=-1比sign=1的数据多一行,则保留第一行sign=-1的数据。
  3. 如果sign=1和sign=-1的数据行一样多,并且最后一行是sign=1,则保留第一行sign=-1和最后一行sign=1的数据。
  4. 如果sign=1和sign=-1的数据行一样多,并且最后一行是sign=-1,则什么也不保留。

在使用CollapsingMergeTree的时候,还有几点需要注意。

(1)折叠数据并不是实时触发的,只有在分区合并的时候才会体现。所以在分区合并之前,用户还是会看到旧的数据。解决这个问题的方式有两种。

在查询数据之前,使用optimize TABLE table_name FINAL命令强制分区合并,但是这种方法效率极低。

需要改变我们的查询方式。以collpase_table举例,如果原始的SQL如下所示:

SELECT id,SUM(code),COUNT(code),AVG(code),uniq(code) FROM collpase_table GROUP BY id ;
则需要改写成如下形式:

SELECT id,SUM(code * sign),COUNT(code * sign),AVG(code * sign),UNIQ(code * sign)
    FROM collpase_table 
    GROUP BY  id 
    HAVING SUM(sign) > 0;

(2)只有相同分区内的数据才有可能被折叠。不过这项限制对于CollapsingMergeTree来说通常不是问题,因为修改或者删除数据的时候,这些数据的分区规则通常都是一致的,并不会改变。

(3)最后这项限制可能是CollapsingMergeTree最大的命门所在。CollapsingMergeTree对于写入数据的顺序有着严格要求。现在用一个示例说明。如果按照正常顺序写入,先写入sign=1,再写入sign=-1,则能够正常折叠:

6.VersionedCollapsingMergeTree

VersionedCollapsingMergeTree表引擎的作用与CollapsingMergeTree完全相同,它们的不同之处在于,对数据的写入顺序没有要求,在同一个分区内,任意顺序的数据都能够完成折叠操作。

在定义VersionedCollapsingMergeTree的时候,除了需要指定sign标记字段以外,还需要指定一个UInt8类型的ver版本号字段:

--示例
CREATE TABLE ver_collpase_table(
    id String,
    code Int32,
    create_time DateTime,
    sign Int8,
    ver UInt8
) ENGINE = VersionedCollapsingMergeTree(sign,ver)
PARTITION BY toYYYYMM(create_time)
ORDER BY id ;

在定义ver字段之后,VersionedCollapsingMergeTree会自动将ver作为排序条件并增加到ORDER BY的末端。以上面的ver_collpase_table表为例,在每个数据分区内,数据会按照ORDER BY id , ver DESC排序。所以无论写入时数据的顺序如何,在折叠处理时,都能回到正确的顺序。

INSERT INTO TABLE ver_collpase_table VALUES('A000',101,now(),1,1);
INSERT INTO TABLE ver_collpase_table VALUES('A000',102,now()',-1,1);
select * from  ver_collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  101 │ 2021-03-11 17:09:47 │    1 │   1 │
└──────┴──────┴─────────────────────┴──────┴─────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  102 │ 2021-03-11 17:09:55 │   -1 │   1 │
└──────┴──────┴─────────────────────┴──────┴─────┘

optimize table ver_collpase_table FINAL;
select * from  ver_collpase_table;


INSERT INTO TABLE ver_collpase_table VALUES('A000',101,now(),-1,1);
INSERT INTO TABLE ver_collpase_table VALUES('A000',102,now(),1,1);
INSERT INTO TABLE ver_collpase_table VALUES('A000',102,now(),1,2);
select * from  ver_collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  1022021-03-11 17:16:3211 │
└──────┴──────┴─────────────────────┴──────┴─────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  1022021-03-11 17:16:3212 │
└──────┴──────┴─────────────────────┴──────┴─────┘
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  1012021-03-11 17:16:32-11 │
└──────┴──────┴─────────────────────┴──────┴─────┘


OPTIMIZE TABLE ver_collpase_table FINAL;
select * from  ver_collpase_table;
┌─id───┬─code─┬─────────create_time─┬─sign─┬─ver─┐
│ A000 │  1022021-03-11 17:16:3212 │
└──────┴──────┴─────────────────────┴──────┴─────┘

7.GraphiteMergeTree

该引擎用来对 Graphite数据进行’瘦身’及汇总。对于想使用CH来存储Graphite数据的开发者来说可能有用。
如果不需要对Graphite数据做汇总,那么可以使用任意的CH表引擎;但若需要,那就采用 GraphiteMergeTree 引擎。它能减少存储空间,同时能提高Graphite数据的查询效率。

好。以上就是MergeTree系列表引擎的基本情况,后续其他表引擎家族都会一一赘述。

了解更多数据库相关知识,请关注微信公众号获取

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45320660/article/details/114969167