2026/4/19 17:42:40
网站建设
项目流程
网站建设推广软件,电子商城网站系统,学习做网站只学过c,市场推广计划方案模板1. 概述特点#xff1a;一定程度上解决了重复数据的问题#xff0c;适用于在后台清理重复数据以节省存储空间虽然 MergeTree 拥有主键#xff0c;但是它的 主键却没有唯一键的约束。这意味着即便多行数据的主键相同#xff0c;它们还是能够被正常写入。在某些使用场合…1. 概述特点一定程度上解决了重复数据的问题适用于在后台清理重复数据以节省存储空间虽然 MergeTree 拥有主键但是它的主键却没有唯一键的约束。这意味着即便多行数据的主键相同它们还是能够被正常写入。在某些使用场合用户并不希望数据表中含有重复的数据。ReplacingMergeTree就是在这种背景下为了数据去重而设计的它能够在合并数据分片 Part 时删除重复的数据在保证查询性能的同时实现了最终一致性的数据更新模型。它的出现确实也在一定程度上解决了重复数据的问题。为什么说是“一定程度”下面会详细介绍ReplacingMergeTree表引擎继承自MergeTree基础表引擎并对数据分片 Part 的合并逻辑进行了调整。ReplacingMergeTree会将所有具有相同排序键的行在数据分片 Part 合并时合并为一行只保留指定版本的最新行。ReplacingMergeTree通过表的ORDER BY子句而非PRIMARY KEY来删除重复记录。即行的唯一性是由表的ORDER BY子句决定的而不是由PRIMARY KEY决定。与常规数据库的 UPDATE 操作不同ReplacingMergeTree的更新是异步和延迟的只在数据合并时发生。合并发生在后台未知时间因此无法提前规划且部分数据可能长时间保持未处理状态(重复数据没有被删除)。尽管可以通过 OPTIMIZE 查询触发一次临时合并但不要依赖这种方式因为 OPTIMIZE 查询会读写大量数据。因此ReplacingMergeTree适用于在后台清理重复数据以节省存储空间但并不能保证数据中完全不存在重复项。2. 语法CREATETABLE[IFNOTEXISTS][db.]table_name[ONCLUSTER cluster](name1[type1][DEFAULT|MATERIALIZED|ALIAS expr1],name2[type2][DEFAULT|MATERIALIZED|ALIAS expr2],...)ENGINEReplacingMergeTree([ver[,is_deleted]])[PARTITIONBYexpr][ORDERBYexpr][PRIMARYKEYexpr][SAMPLEBYexpr][SETTINGS namevalue,...]从上面可以看到创建一张ReplacingMergeTree表的方法与创建普通MergeTree表无异只需要替换 EngineENGINEReplacingMergeTree([ver[,is_deleted]])其中ver是一个表示版本号的可选参数。is_deleted是一个表示当前行状态的可选参数只有在使用ver时才可以启用is_deleted。3. 特性3.1 版本控制策略可以通过指定一个UInt*、Date或者DateTime类型的字段作为版本号ver来决定数据如何去重。在合并时ReplacingMergeTree会在所有具有相同排序键的行中只保留一行显式版本控制如果指定了版本号ver则保留具有最大版本号的行。如果多行的ver相同保留最新插入的那一行。隐式版本控制如果未设置版本号ver则保留最新插入的那一行。3.1.1 显式版本控制显式版本控制是指指定版本号ver那么就会保留具有最大版本号的行。如果多行的版本号相同保留最新插入的那一行。版本列最常用的方式是时间戳或递增IDCREATETABLEreplacing_merge_tree_v1(id String,code String,create_timeDateTime)ENGINEReplacingMergeTree(create_time)PARTITIONBYtoYYYYMM(create_time)ORDERBYid;replacing_merge_tree_v1基于 id 字段(排序键)去重并且使用 create_time 字段作为版本号。现在向表中插入如下数据INSERTINTOreplacing_merge_tree_v1Values(1,A3,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v1Values(1,A2,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v1Values(1,A1,2026-01-01 00:00:00);那么在删除重复数据的时候会在 id 相同时保留 create_time 最大最新的那一行SELECT*FROMreplacing_merge_tree_v1 FINAL;┌─id─┬─code─┬─────────create_time─┐ │1│ A2 │2026-01-0101:01:01│ └────┴──────┴─────────────────────┘FINAL 语法下面会详细介绍。3.1.2 隐式版本控制无版本列隐式版本控制是指不指定版本列ReplacingMergeTree默认保留最后插入的行CREATETABLEreplacing_merge_tree_v2(id String,code String,create_timeDateTime)ENGINEReplacingMergeTree()PARTITIONBYtoYYYYMM(create_time)ORDERBYid;replacing_merge_tree_v2还是基于 id 字段(排序键)去重但相比于replacing_merge_tree_v1没有指定版本号ver。现在向表中插入如下数据INSERTINTOreplacing_merge_tree_v2Values(1,A3,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v2Values(1,A2,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v2Values(1,A1,2026-01-01 00:00:00);那么在删除重复数据的时候会在 id 相同时保留最后插入的行SELECT*FROMreplacing_merge_tree_v2 FINAL;┌─id─┬─code─┬─────────create_time─┐ │1│ A1 │2026-01-0100:00:00│ └────┴──────┴─────────────────────┘3.2 状态控制版本号ver决定了相同排序键ORDER BY行的保留优先级而is_deleted则标记行的逻辑状态(UInt8类型的可选参数)1 表示行被删除0 表示行未被删除(有效行)CREATETABLEreplacing_merge_tree_v3(id String,code String,create_timeDateTime,is_deleted UInt8)ENGINEReplacingMergeTree(create_time,is_deleted)PARTITIONBYtoYYYYMM(create_time)ORDERBYid;需要注意的是只有在使用ver时才可以启用is_deleted。replacing_merge_tree_v3还是基于 id 字段(排序键)去重同时指定版本号ver但相比于replacing_merge_tree_v1还设置行状态标记is_deleted。现在向表中插入如下数据INSERTINTOreplacing_merge_tree_v3Values(1,A1,2026-01-01 01:01:01,0);INSERTINTOreplacing_merge_tree_v3Values(1,A1,2026-01-01 01:01:01,1);那么在合并删除重复数据时根据版本号会保留版本号最大的一行数据如果插入的两行数据具有相同的版本号则会保留最后插入的那一行。由于最后一行is_deleted 1 表示被删除(删除行)所以查询无返回行SELECT*FROMreplacing_merge_tree_v3 FINAL;0rowsinset.Elapsed:0.003sec.3.3 查询模式 FINAL在合并阶段ReplacingMergeTree使用 ORDER BY 列中的值作为唯一标识来识别重复行并仅保留版本最高的那一行。不过这种方式只能在最终状态上接近正确它并不保证查询时所有重复行都会被去重因此不应将其作为严格依赖。由于更新和删除记录在查询时仍可能被计算在内查询结果因此可能不正确。为了获得准确的结果用户需要在后台合并的基础上再配合查询时去重以及删除记录的剔除来实现这就需要通过FINAL运算符来完成这一需求。假设我们有如下表CREATETABLEreplacing_merge_tree_v4(id String,code String,create_timeDateTime)ENGINEReplacingMergeTree(create_time)PARTITIONBYtoYYYYMM(create_time)ORDERBYid;replacing_merge_tree_v4还是基于 id 字段(排序键)去重同时指定版本号ver。现在向表中插入如下数据INSERTINTOreplacing_merge_tree_v4Values(1,A3,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v4Values(1,A2,2026-01-01 01:01:01);INSERTINTOreplacing_merge_tree_v4Values(1,A1,2026-01-01 00:00:00);在不使用FINAL的情况下进行查询返回结果没有达到去重的效果具体情况会因合并情况而异SELECT*FROMreplacing_merge_tree_v4;┌─id─┬─code─┬─────────create_time─┐ │1│ A2 │2026-01-0101:01:01│ └────┴──────┴─────────────────────┘ ┌─id─┬─code─┬─────────create_time─┐ │1│ A1 │2026-01-0100:00:00│ └────┴──────┴─────────────────────┘ ┌─id─┬─code─┬─────────create_time─┐ │1│ A3 │2026-01-0101:01:01│ └────┴──────┴─────────────────────┘添加FINAL后得到了预期结果SELECT*FROMreplacing_merge_tree_v4 FINAL;┌─id─┬─code─┬─────────create_time─┐ │1│ A2 │2026-01-0101:01:01│ └────┴──────┴─────────────────────┘因此可以通过FINAL运算符在查询时实现去重以及删除记录的剔除最终获得准确的结果。