ClickHouse 实战:深入了解 MergeTree 家族 II 之 ReplacingMergeTree 表引擎
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运算符在查询时实现去重以及删除记录的剔除最终获得准确的结果。

相关新闻

从本地到生产环境:GPEN图像修复模型部署全流程详解

从本地到生产环境:GPEN图像修复模型部署全流程详解

从本地到生产环境:GPEN图像修复模型部署全流程详解 1. 为什么需要一套完整的GPEN部署方案? 你是不是也遇到过这样的情况:在GitHub上找到一个效果惊艳的图像修复模型,clone下来跑通demo后兴奋不已,可一想“怎么让设计…

2026/7/3 16:50:50 阅读更多 →
ccmusic-database/music_genreGPU利用率提升:批处理+缓存机制调优实践

ccmusic-database/music_genreGPU利用率提升:批处理+缓存机制调优实践

ccmusic-database/music_genre GPU利用率提升:批处理缓存机制调优实践 1. 为什么GPU跑不满?——从音乐流派分类应用的实际瓶颈说起 你有没有遇到过这种情况:明明配了A10或RTX4090,跑音乐流派分类Web应用时GPU利用率却总在20%~40…

2026/7/3 13:53:05 阅读更多 →
SiameseUIE中文-base部署案例:Docker镜像封装与生产环境端口映射

SiameseUIE中文-base部署案例:Docker镜像封装与生产环境端口映射

SiameseUIE中文-base部署案例:Docker镜像封装与生产环境端口映射 1. 为什么需要封装成Docker镜像 在实际项目中,我们经常遇到这样的问题:模型本地跑得好好的,一到服务器上就报错;开发环境用Python 3.11,测…

2026/7/3 16:50:56 阅读更多 →

最新新闻

.NET Core 的 重要问题

.NET Core 的 重要问题

.NET Core 的 重要问题 什么是 C# ?.NET 中主要的开发语言,.NET 只是一个开发平台,他提供了一些类,一些运行时等等;他不是一门语言,除了 C# , 还有 VB.NET,F# 等等;但是用的最多的,…

2026/7/4 9:53:40 阅读更多 →
Agent Skills技能缓存策略:优化技能加载速度的3层缓存架构

Agent Skills技能缓存策略:优化技能加载速度的3层缓存架构

Agent Skills技能缓存策略:优化技能加载速度的3层缓存架构 【免费下载链接】agentskills Specification and documentation for Agent Skills 项目地址: https://gitcode.com/GitHub_Trending/ag/agentskills 在AI应用开发中,Agent Skills的加载速…

2026/7/4 9:51:40 阅读更多 →
Windows Research Kernel (WRK) 本地过程调用(LPC):Windows进程间通信的内核实现

Windows Research Kernel (WRK) 本地过程调用(LPC):Windows进程间通信的内核实现

Windows Research Kernel (WRK) 本地过程调用(LPC):Windows进程间通信的内核实现 【免费下载链接】Windows-Research-Kernel-WRK- Windows Research Kernel Source Code 项目地址: https://gitcode.com/gh_mirrors/wi/Windows-Research-Kernel-WRK- Windows …

2026/7/4 9:49:40 阅读更多 →
BLDC无感控制:脉冲注入与电感法优化方案

BLDC无感控制:脉冲注入与电感法优化方案

1. 项目背景与核心挑战在电机控制领域,无刷直流电机(BLDC)因其高效率、长寿命和低维护成本等优势,正逐步取代传统有刷电机。但无感控制方案(即不使用霍尔传感器)的性能提升一直是行业痛点。传统反电动势法在…

2026/7/4 9:47:39 阅读更多 →
从0到1学习sokol-samples:面向绝对初学者的完整路线图 [特殊字符]

从0到1学习sokol-samples:面向绝对初学者的完整路线图 [特殊字符]

从0到1学习sokol-samples:面向绝对初学者的完整路线图 🚀 【免费下载链接】sokol-samples Sample code for https://github.com/floooh/sokol 项目地址: https://gitcode.com/gh_mirrors/so/sokol-samples 想要快速掌握现代图形编程却不知从何入手…

2026/7/4 9:47:39 阅读更多 →
中间件简介

中间件简介

中间件是指位于应用程序和操作系统之间的软件组件,用于协调和连接不同的系统、服务或组件,以实现数据传输、通信和功能扩展。它们在分布式系统、网络通信和应用集成中起着关键的作用。 那么常见的中间件有哪些呢? 消息队列中间件&#xff1…

2026/7/4 9:45:38 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻