说明
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具体过程
- 首先,使用where条件找到需要修改的分区;
- 然后,重建每个分区,用新的分区替换旧的,分区一旦被替换,就不可回退;
对于每个分区,可以认为是原子性的;但对于整个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