clickhouse21.7.11.3 Mutation

说明

clickhourse 是 OLAP 数据库,不支持 delete、update 操作,但可以通过 Mutation 操作实现,本文讲解 Mutation

执行的mutation 操作保存在 ClickHouse 的 system.mutations 表中

提示: delete、update SQL见 链接

官网链接:
https://clickhouse.com/docs/en/sql-reference/statements/alter/#mutations

有以下缺点

  • 是 很重 的操作,因为每次 delete、update,都会导致 重新分区
  • 不支持事务,一旦语句被提交执行,就会立刻对现有数据产生影响,无法回滚;
  • Mutation语句的执行是一个异步的后台过程,语句被提交之后就会立即 返回成功,但是,当数据量大时,不会立即执行,即:立即查询,数据仍然存在。

    提示:由于一般测试的数据很少,DELETE 操作给人的感觉是立即执行的

mutations 表

当执行 删除数据、修改数据后,执行下面语句:

select * from  system.mutations

字段解释:

字段名 类型 说明
database String 应用 mutation 的数据库名
table String 应用 mutation 的表名。
mutation_id String mutation_id.txt 文件名
command String mutation 命令的字符串,ALTER TABLE [db.]table 之后的部分
create_time DateTime 提交 mutation 命令的时间
block_numbers.partition_id Array(String) 对于 replicated 表,数组包含分区 ID(每个分区一个记录),对于非 replicated 表的 mutation ,数组为空。
block_numbers.number Array(Int64) 对于 replicated 表,数组包含每一个分区的一条记录以及mutation 获得的 block 数字,只有包含数字小于此数字的 block 部分才会在分区中发生 mutation。在非 replicated 表中,所有分区中的 block 数字形成一个序列,这意味着对于非 replicated表的 mutation,该列将包含一条记录,该记录具有通过 mutation 获得的单个 block 数字。
parts_to_do_names Array(String) 完成 mutation 而需要 mutation 的数据部分的array 的名称
parts_to_do Int64 需要 mutation 才能完成 mutation 的数据部分的数量
is_done UInt8 mutation 是否完成的标志。1 表示完成;0 表示正在进行中。【说明】即使 parts_to_do=0,由于长时间运行 insert 查询,replicated 表的 mutation 可能尚未完成,这将创建需要 mutation 的新数据部分。
latest_failed_part String 无法改变的最新部分的名称
latest_fail_time DateTime 最近失败的日期和时间
latest_fail_reason String 最近失败的异常消息

Mutation具体过程

  1. 首先,使用where条件找到需要修改的分区;
  2. 然后,重建每个分区,用新的分区替换旧的,分区一旦被替换,就不可回退;

对于每个分区,可以认为是原子性的;但对于整个mutation,如果涉及多个分区,则不是原子性的。

注意事项

  • 更新功能不支持更新有关主键或分区键的列
  • 更新操作没有原子性,即在更新过程中select结果很可能是一部分变了,一部分没变,从上边的具体过程就可以知道
  • 更新是按提交的顺序执行的
  • 更新一旦提交,不能撤销,即使重启clickhouse服务,也会继续按照system.mutations的顺序继续执行
  • 已完成更新的条目不会立即删除,保留条目的数量由finished_mutations_to_keep存储引擎参数确定。 超过数据量时旧的条目会被删除
  • 更新可能会卡住,比如 update intvalue='abc' 这种类型错误的更新语句执行不过去,那么会一直卡在这里,此时,可以使用 KILL MUTATION 来取消,语法:
    // database、table是system.mutations表中的字段
    kill kutation where database='数据库名' and table='表名'
    

使用建议

按照官方的说明,update/delete 的使用场景是一次更新大量数据,也就是where条件筛选的结果应该是一大片数据。

举例:

alter table test update status=1 where status=0 and day='2020-04-01'

一次更新一天的数据。

不建议使用

也可以更新一条数据,但频繁的这种操作,可能会对服务造成压力。

如果只更新一条数据,工作量小,也需要重建分区,效率低下

对于频繁单条更新的这种场景,建议使用 ReplacingMergeTree 引擎来变相解决

排错

通过该表进行排错,见下面链接:
https://blog.csdn.net/github_39577257/article/details/103181537

参考文章:
https://www.jianshu.com/p/521f2d1611f8


原文出处:/show_1IX3QPvX8Wy3.html