首页IT科技clickhouse join 内存不足(ClickHouse引擎之ReplacingMergeTree)

clickhouse join 内存不足(ClickHouse引擎之ReplacingMergeTree)

时间2025-06-18 21:02:28分类IT科技浏览5840
导读:为什么会有ReplacingMergeTree ReplacingMergeTree作用?...

为什么会有ReplacingMergeTree

ReplacingMergeTree作用?

ClickHouse中最常用也是最基础的表引擎为MergeTree                ,在它的功能基础上添加特定功能就构成了MergeTree系列引擎            。MergeTree支持主键                   ,但主键主要用来缩小查询范围      ,且不具备唯一性约束            ,可以正常写入相同主键的数据                      。但在一些情况下                    ,可能需要表中没有主键重复的数据       。ReplacingMergeTree就是在MergeTree的基础上加入了去重的功能         ,但它仅会在合并分区时        ,去删除重复的数据                     ,写入相同数据时并不会引发异常         。

使用方式

创建一张ReplacingMergeTree的表和创建MergeTree类似            ,修改引擎即可                     。ReplacingMergeTree引擎创建规范为:ENGINE = ReplacingMergeTree([ver])    ,其中ver为选填参数                      ,它需要指定一个UInt8/UInt16                、Date或DateTime类型的字段               ,它决定了数据去重时所用的算法,如果没有设置该参数                   ,合并时保留分组内的最后一条数据;如果指定了该参数                  ,则保留ver字段取值最大的那一行           。

不指定ver参数

-- 创建未指定ver参数ReplacintMergeTree引擎的表 CREATE TABLE replac_merge_test ( `id` String, `code` String, `create_time` DateTime ) ENGINE = ReplacingMergeTree() PARTITION BY toYYYYMM(create_time) PRIMARY KEY id ORDER BY (id, code)

ReplacingMergeTree会根据ORDER BY所声明的表达式去重

-- 在上述表中插入数据 insert into replac_merge_test values (A000, code1, now()),(A000, code1, 2020-07-28 21:30:00), (A001, code1, now()), (A001, code2, 2020-07-28 21:30:00), (A0002, code2, now()); -- 查询当前数据 select * from replac_merge_test; ┌─id────┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-07-28 21:23:48 │ │ A000 │ code1 │ 2020-07-28 21:30:00 │ │ A0002 │ code2 │ 2020-07-28 21:23:48 │ │ A001 │ code1 │ 2020-07-28 21:23:48 │ │ A001 │ code2 │ 2020-07-28 21:30:00 │ └───────┴───────┴─────────────────────┘ -- 强制进行分区合并 optimize table replac_merge_test FINAL; -- 再次查询数据 select * from replac_merge_test; ┌─id────┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-07-28 21:30:00 │ │ A0002 │ code2 │ 2020-07-28 21:23:48 │ │ A001 │ code1 │ 2020-07-28 21:23:48 │ │ A001 │ code2 │ 2020-07-28 21:30:00 │ └───────┴───────┴─────────────────────┘

通过上面示例可以看到   ,id                   、code相同的字段’A000’,code1’被去重剩余一条数据                ,由于创建表时没有设置ver参数                   ,故保留分组内的最后一条数据(create_time字段)

-- 再次使用insert插入一条数据 insert into replac_merge_test values (A001, code1, 2020-07-28 21:30:00); -- 查询表中数据 select * from replac_merge_test; ┌─id────┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-07-28 21:30:00 │ │ A0002 │ code2 │ 2020-07-28 21:23:48 │ │ A001 │ code1 │ 2020-07-28 21:23:48 │ │ A001 │ code2 │ 2020-07-28 21:30:00 │ └───────┴───────┴─────────────────────┘ ┌─id───┬─code──┬─────────create_time─┐ │ A001 │ code1 │ 2020-07-28 21:30:00 │ └──────┴───────┴─────────────────────┘

可以看到      ,再次插入重复数据时            ,查询仍然会存在重复      。在ClickHouse中                    ,默认一条insert插入的数据为同一个数据分区         ,不同insert插入的数据为不同的分区        ,所以ReplacingMergeTree是以分区为单位进行去重的                     ,也就是说只有在相同的数据分区内            ,重复数据才可以被删除掉                    。只有数据合并完成后    ,才可以使用引擎特性进行去重               。

指定ver参数

-- 创建指定ver参数ReplacingMergeTree引擎的表 CREATE TABLE replac_merge_ver_test ( `id` String, `code` String, `create_time` DateTime ) ENGINE = ReplacingMergeTree(create_time) PARTITION BY toYYYYMM(create_time) PRIMARY KEY id ORDER BY (id, code) -- 插入测试数据 insert into replac_merge_ver_test values(A000, code1, 2020-07-10 21:35:30),(A000, code1, 2020-07-15 21:35:30),(A000, code1, 2020-07-05 21:35:30),(A000, code1, 2020-06-05 21:35:30); -- 查询数据 select * from replac_merge_ver_test; ┌─id───┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-06-05 21:35:30 │ └──────┴───────┴─────────────────────┘ ┌─id───┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-07-10 21:35:30 │ │ A000 │ code1 │ 2020-07-15 21:35:30 │ │ A000 │ code1 │ 2020-07-05 21:35:30 │ └──────┴───────┴─────────────────────┘ -- 强制进行分区合并 optimize table replac_merge_ver_test FINAL; -- 查询数据 select * from replac_merge_ver_test; ┌─id───┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-07-15 21:35:30 │ └──────┴───────┴─────────────────────┘ ┌─id───┬─code──┬─────────create_time─┐ │ A000 │ code1 │ 2020-06-05 21:35:30 │ └──────┴───────┴─────────────────────┘

由于上述创建表是以create_time的年月来进行分区的                      ,可以看出不同的数据分区               ,ReplacingMergeTree并不会进行去重,并且在相同数据分区内                   ,指定ver参数后                  ,会保留同一组数据内create_time时间最大的那一行数据   。

总结

使用ORDER BY排序键   ,作为判断数据是否重复的唯一键

只有在合并分区时                ,才会触发数据的去重逻辑

删除重复数据                   ,是以数据分区为单位                   。同一个数据分区的重复数据才会被删除      ,不同数据分区的重复数据仍会保留

在进行数据去重时            ,由于已经基于ORDER BY排序                    ,所以可以找到相邻的重复数据

数据去重策略为:

若指定了ver参数         ,则会保留重复数据中        ,ver字段最大的那一行

若未指定ver参数                     ,则会保留重复数据中最末的那一行数据

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
如何优化网站SEO排名(让你的网站排名飞升) linux测试环境搭建教程(TestLink运行环境:Redhat5+Apache2.2.17+php5.3.5+MySQL5.5.91)