前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ReplacingMergeTree得到史诗级加强,我不允许大家不知道

ReplacingMergeTree得到史诗级加强,我不允许大家不知道

作者头像
Nauu
发布2023-09-02 10:55:36
5940
发布2023-09-02 10:55:36
举报
文章被收录于专栏:ClickHouse的秘密基地

MergeTree家族枝繁叶茂,人数众多。

但要选个最能打的,ReplacingMergeTree肯定算一个。

Long Long Ago,天地浑浊,ReplacingMergeTree出现了。

起初,它的出现是为了解决重复数据的问题。再往后,利用新版本覆盖旧版本的特性,人们就变相实现了 UPDATE 的功能。

大家一看,INSERT、UPDATE 都有了,那索性再来个 DELETE 吧。于是利用 ReplacingMergeTree 的删除方案就有了,在表上加一个_delete字段,0表示有效,1表示无效。查询的时候把_delete=1的过滤掉。

皆大欢喜,增删改查都齐活了。

But,这种删除方案还是有缺点:

  • 查询的时候过滤要自己实现,有点麻烦
  • _delete=1的数据并没有被物理删除

时光荏苒,斗转星移,一晃就到2023年了。在 ClickHouse 的新版本中,ReplacingMergeTree 又得到了史诗级加强,居然内置了删除能力。这么一来,你让 CollapsingMergeTree 怎么活呀。

新版本中,ReplacingMergeTree(ver, is_deleted) 多了一个选填参数,

代码语言:javascript
复制
`is_deleted`:Column data type — `Int8`.
1:删除
0:正常
必须和ver一起使用

接下来举例说明:

创建一张表:

代码语言:javascript
复制
CREATE TABLE replace_test_a(
  user_id UInt64,
  score String,
  is_deleted UInt8 DEFAULT 0,
  create_time DateTime DEFAULT toDateTime(0)
)ENGINE= ReplacingMergeTree(create_time,is_deleted)
ORDER BY user_id

写入1000w数据:

代码语言:javascript
复制
INSERT INTO TABLE replace_test_a(user_id,score)
WITH(
  SELECT ['A','B','C','D','E','F','G']
)AS dict
SELECT number AS user_id, dict[number%7+1] FROM numbers(10000000)

SELECT *
FROM replace_test_a
LIMIT 5

Query id: b023c6e8-6a3f-4419-887a-d024b808c20f

┌─user_id─┬─score─┬─is_deleted─┬─────────create_time─┐
│       0 │ A     │          0 │ 1970-01-01 08:00:00 │
│       1 │ B     │          0 │ 1970-01-01 08:00:00 │
│       2 │ C     │          0 │ 1970-01-01 08:00:00 │
│       3 │ D     │          0 │ 1970-01-01 08:00:00 │
│       4 │ E     │          0 │ 1970-01-01 08:00:00 │
└─────────┴───────┴────────────┴─────────────────────┘

修改1行数据, 将 user_id=0的 改成 AAAA:

代码语言:javascript
复制
INSERT INTO TABLE replace_test_a(user_id,score,create_time) VALUES(0,'AAAA',now())

SELECT *
FROM replace_test_a
FINAL
LIMIT 5

Query id: e01df531-6c81-4ef0-a079-05f78293e4de

┌─user_id─┬─score─┬─is_deleted─┬─────────create_time─┐
│       0 │ AAAA  │          0 │ 2023-06-29 19:39:27 │
│       1 │ B     │          0 │ 1970-01-01 08:00:00 │
│       2 │ C     │          0 │ 1970-01-01 08:00:00 │
│       3 │ D     │          0 │ 1970-01-01 08:00:00 │
│       4 │ E     │          0 │ 1970-01-01 08:00:00 │
└─────────┴───────┴────────────┴─────────────────────┘

可以看到,修改成功。

接下来是重头戏,我们删除user_id=0的数据:

代码语言:javascript
复制
INSERT INTO TABLE replace_test_a(user_id,score,is_deleted,create_time) VALUES(0,'AAAA',1,now())

SELECT *
FROM replace_test_a
FINAL
LIMIT 5

Query id: 2b1b10f7-884d-4dfd-a9a2-8982cb899292

┌─user_id─┬─score─┬─is_deleted─┬─────────create_time─┐
│       1 │ B     │          0 │ 1970-01-01 08:00:00 │
│       2 │ C     │          0 │ 1970-01-01 08:00:00 │
│       3 │ D     │          0 │ 1970-01-01 08:00:00 │
│       4 │ E     │          0 │ 1970-01-01 08:00:00 │
│       5 │ F     │          0 │ 1970-01-01 08:00:00 │
└─────────┴───────┴────────────┴─────────────────────┘

删除成功,接下来删除前50w行试试:

代码语言:javascript
复制
INSERT INTO TABLE replace_test_a(user_id,score,is_deleted,create_time)
WITH(
  SELECT ['AA','BB','CC','DD','EE','FF','GG']
)AS dict
SELECT number AS user_id, dict[number%7+1],1, now() AS create_time FROM numbers(500000)


SELECT COUNT()
FROM replace_test_a
FINAL

Query id: 3e738515-b23c-48de-80ca-c90eb35ed6df

┌─count()─┐
│ 9500000 │

数据少了50w行,删除成功。

ReplacingMergeTree的实现原理是:

  • 查询时过滤 is_deleted = 1 的数据
  • Merge时物理删除is_deleted = 1 的数据

赶快去试试这项新功能吧。

btw,我在例子里的查询都带了FINAL。FINAL的性能在新版本中也得到了加强,以后我会专门写一篇解析的文章。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ClickHouse的秘密基地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档