ClickHouse系列教程三:MergeTree引擎分析

ClickHouse系列教程: ClickHouse系列教程


Clickhouse之MergeTree引擎分析
CRUD
Clickhouse支持查询(select)和增加(insert),但是不直接支持更新(update)和删除(delete)。
插入:MergeTree不是LSM树,因为它不包含“memtable”和“log”:插入的数据直接写入文件系统。这使得它仅适用于批量插入数据,而不是非常频繁地插入单行; 每秒一次插入很好,但是每秒一千次不行。如果有大量内容想要插入,可以使用Buffer引擎,Buffer引擎做的是把缓冲数据写入RAM,定期将其刷新到另一个表。
Clickhouse是没有update和delete命令的,根据官方的说法:ClickHouse是以性能为导向的系统,想要性能最好,但修改过的数据很难进行比较好的存储和处理。
Clickhouse通过ALTER的变种实现了UPDATE和DELETE。
Mutations(突变)是一种ALTER查询变体,允许更改或删除表中的行。突变适用于更改表中许多行的操作(单行操作也是可以的)。
该功能处于测试阶段,从1.1.54388版本开始提供。 Mutations的更新功能是版本18.12.14开始提供的,目前MergeTree引擎支持Mutations。
现有表已准备好按原样进行突变(无需转换),但在将第一个突变应用于表后,其元数据格式将与先前的服务器版本不兼容,并且回退到先前版本变得不可能。
命令如下:
ALTER TABLE [db.]table DELETE WHERE filter_expr;
ALTER TABLE [db.]table UPDATE column1 = expr1 [, …] WHERE filter_expr;
注意:更新功能不支持更新有关主键或分区键的列。
对于
MergeTree表,通过重写整个数据部分来执行突变。此操作没有原子性 - 一旦完成准备就会替换突变部分,并且在突变开始执行后,SELECT的查询将看到来自已经突变的部分的数据以及尚未突变的部分的数据。
突变按其创建顺序排序,并按顺序应用于每个部分。INSERT也部分地进行了突变 - 在提交突变之前插入表中的数据将被突变,之后插入的数据将不会被突变。请注意,突变不会以任何方式阻止INSERT。
突变本身使用系统配置文件设置异步执行。要跟踪突变的进度,您可以使用system.mutations表。即使ClickHouse服务器重新启动,成功提交的突变也将继续执行。一旦提交突变,就无法回滚突变,但如果突变由于某种原因而被卡住,则可以通过KILL MUTATION取消突变。
已完成突变的条目不会立即删除,保留条目的数量由finished_mutations_to_keep存储引擎参数确定。 旧的突变条目会被删除。
突变的具体实现过程是先使用where条件找到需要修改的parts(分区),然后重建每个part,用新的part替换旧的part。对于有大的part的表进行重建会很耗费时间(默认一个part最大大小为150G )。突变在每个小的part是原子性的。
如果不想使用突变,毕竟突变不是原子性,而且开销较大,另外一个比较好的选择是使用ReplacingMergeTree替代MergeTree。ReplacingMergeTree会删除主键相同的重复项,删除操作会在合并的过程中完成。而合并是在后台不定时地做,因此你无法预先知道数据是否合并完成。ReplacingMergeTree有个可选字段ver,类型可以为UInt*,Date或者DateTime。合并的时候,ReplacingMergeTree 从同一个分区中的所有具有相同主键的行中选择一行留下 如果 ver 列未指定,选择最后一条; 如果 ver 列已指定,选择 ver 值最大的版本留下。注意:ReplacingMergeTree去重不同分区中的相同主键的行。示例如下:
create table t2 (birth Date, id UInt16, name String, point UInt16,ver UInt8) ENGINE=ReplacingMergeTree(birth, (id, name), 8192,ver);

insert into t2(birth, id, name, point,ver) values (‘2017-04-01’, 1, ‘qwe’, 10,0);
insert into t2(birth, id, name, point,ver) values (‘2017-06-01’, 4, ‘asd’, 15,0);
insert into t2(birth, id, name, point,ver) values (‘2017-04-03’, 5, ‘zxc’, 11,0);
insert into t2(birth, id, name, point,ver) values (‘2017-04-01’, 1, ‘qwe’, 100,1);

select * from t2;

现在2个版本的内容都在,等待优化完成后只保留一个:

如果不想等待,可以在select时在表名后增加关键字FINAL ,但这样会导致查询变慢:
select birth, id, name, point, ver from t2 FINAL ;

分区规则分析
一个分区是指按指定规则逻辑组合一起的表的记录集,可以按任意标准进行分区,如按月,按日或按事件类型。为了减少需要操作的数据,每个分区都是分开存储的。访问数据时,ClickHouse 尽量使用这些分区的最小子集。
分区的使用是为了提高性能,因为分区键列的最小值和最大值存储在每个表部分中,这些值可用于修剪查询所需的表部分。但它的主要用途是促进数据操作任务(例如丢弃旧数据)。如果主键使用得很好,那么分区不会提高性能。
MergeTree引擎默认是以表中的Date字段作为分区 (partitions)的标志。如果不手动指定,Clickhouse会把Date字段的年和月自动作为分区的标准。
下面是运行实例:
drop table t;
create table t (birth Date, id UInt16, name String, point UInt16) ENGINE=MergeTree(birth, (id, name), 10);
insert into t(birth, id, name, point) values (‘2017-04-01’, 1, ‘qwe’, 10);
insert into t(birth, id, name, point) values (‘2017-06-01’, 4, ‘asd’, 15);
insert into t(birth, id, name, point) values (‘2017-04-03’, 5, ‘zxc’, 11);
所有表的分区情况都存在system.parts这个表中,查询分区情况:
SELECT name,min_date,max_date,min_block_number,max_block_number,level,partition,active
FROM system.parts
WHERE table = ‘t’;

Name是这个分区的名字,比如说20170401_20170401_1_1_0是由
min_date,分区中最小的日期:20170401
max_date,分区中最大的日期:20170401
min_block_number,数据块的最小编号
max_block_number,数据块的最大编号
level,块级别,即在由块组成的合并树中,该块在树中的深度
组成的。
最后一个参数activate是指这个分区是否处于激活状态,1为激活状态,0为非激活状态。非激活片段是那些在合并到较大片段之后剩余的源数据片段。损坏的数据片段也表示为非活动状态。
这时文件夹的目录组织如下:

其中detached 目录存放着使用 DETACH 语句从表中分离的分区片段。损坏的片段也会移到该目录,而不是删除。服务器不使用detached目录中的分区片段。
ClickHouse 大约在插入后15分钟定期报告合并操作,合并插入的数据片段。此外,你也可以使用 OPTIMIZE 语句直接执行合并:
OPTIMIZE TABLE t PARTITION 201704;
合并后再次查看分区情况:

新增一个分区,同时旧的2个分区的激活状态变为0。非合并部分将在合并后约10分钟删除:

那些有相同分区表达式值的数据片段才会合并。这意味着 你不应该用太精细的分区方案(超过一千个分区)。否则,会因为文件系统中的文件数量和需要找开的文件描述符过多,导致 SELECT 查询效率不佳。 不同分区之间的文件是永远不会合并的。

3.1 一条数据写入后,数据写入文件后有哪些类型文件?每种类型文件的存储结构是如何的(加上图示)?

文件存储结构
前面提到的这个表:
birth Date, id UInt16, name String, point UInt16

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值