Clickhouse源码分析-TTL执行流程

第一种情况:无ttl_only_drop_parts配置

总体示例以及说明

如果没有ttl_only_drop_parts的配置,过期数据的删除(这里是删除,是将过期的数据从这个part删除,并将过期的数据构成一个part,这个过期的part标记为inactive,没过期的变为新part)会在TTL Merge任务中进行。

示例如下,ttl_only_drop_parts = 0:

CREATE TABLE my_table1
(
    `event_time` DateTime,
    `id` UInt64,
    `message` String
)
ENGINE = MergeTree
PARTITION BY toStartOfHour(event_time)
ORDER BY (event_time, id)
TTL event_time + toIntervalMinute(3)
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 0

 插入数据:

INSERT INTO my_table1
SELECT
    now() - INTERVAL intDiv(number, 1000) SECOND AS event_time,  -- 控制时间分布在最近3分钟
    number AS id,
    concat('message_', toString(number)) AS message
FROM numbers(1000000);

这条 SQL 语句的作用是:my_table1 表插入 1,000,000 条数据,这些数据的 event_time 字段分布在最近 3 分钟内

此时100W的数据中,会有两个分区生成:2025-06-30 12:00:00,2025-06-30 13:00:00。

过了一段时间后,由于2025-06-30 12:00:00中已经有部分数据达到过期时间,所以会生成一个1751284800_2_2_1的part,它的active字段为1。

而之前的那个老分区直接设置active字段为0即可,表示为不活跃。

用图解可以表示为:

过一段时间之后:

此时可以看到1751284800_2_2_0中的部分数据也达到了过期时间,之后生成一个名字为1751284800_2_2_1的分区,剩余数据为168000行,相当于过期了1000行。

此部分可以用图解表示为:

再过一段时间可以看到:

此时cleanup后台线程进行了清理后,剩下了最后两个part: 

这里大家可能会有疑问?为什么最后两个part迟迟没有删除呢,它们明明已经到达了最大过期时间了啊?

这个结论放在 <分区到达过期时间却未删除> 这一小节说明。

梳理part的转变

我们也可以从part_log中梳理关于这个表TTL merge:

1️⃣最初插入的数据,ClickHouse 生成了以下两个原始 part:

TimeEventPart NameRows分区
13:02:48NewPart1751284800_2_2_08310002025-06-30 13:00:00
13:02:48NewPart1751288400_1_1_01690002025-06-30 12:00:00

这两个 part 加起来就是插入的 1,000,000 行 ✅

2️⃣ ClickHouse 执行 TTL 删除合并1:

TimeEventPart NameRows类型
13:02:48MergePartsStart1751284800_2_2_10开始 TTL 合并
13:02:48MergeParts1751284800_2_2_111000TTL 合并后剩下的数据

3️⃣ ClickHouse 执行 TTL 删除合并2:

TimeEventPart NameRows类型
13:03:00MergePartsStart1751288400_1_1_10开始 TTL 合并
13:03:00MergeParts1751288400_1_1_1168000TTL 合并后剩下的数据

4️⃣清理不活跃的分区

TimeEventPart NameRows说明
13:12:12RemovePart1751284800_2_2_0831000被后台clean线程删掉
13:12:12RemovePart1751288400_1_1_0169000被后台clean线程删掉

分区到达过期时间却未删除

在上面,我们看到了分区达到过期时间,但是却未删除的场景,这是为什么呢?

此时os time:

$ date
Mon Jun 30 01:41:14 PM UTC 2025

这与一个参数有关系:merge_with_ttl_timeout

官网链接如下:Manage Data with TTL (Time-to-live) | ClickHouse Docs

对于后台merge线程选择一个TTL Merge任务(也就是类型为TTLDelete的merge任务)后,它会推迟这个分区向后merge_with_ttl_timeout 毫秒,才能再次选择这个分区。

例如依据上面的示例来说,假如2025-06-30 13:00:00在13:03:00执行,那么下次能选择到分区为2025-06-30 13:00:00的part进行merge,至少在13:03:00 + 4h = 15:03:00 才能发生。

4h为merge_with_ttl_timeout的默认值(转化为小时)。

关键代码位置,更新分区的选择时机:

void MergeTreeDataMergerMutator::updateTTLMergeTimes(const MergeSelectorChoice & merge_choice, const MergeTreeSettingsPtr & settings, time_t current_time)
{chassert(!merge_choice.range.empty());const String & partition_id = merge_choice.range.front().info.getPartitionId();switch (merge_choice.merge_type){case MergeType::Regular:/// Do not update anything for regular merge.return;case MergeType::TTLDelete:next_delete_ttl_merge_times_by_partition[partition_id] = current_time + (*settings)[MergeTreeSetting::merge_with_ttl_timeout];return;case MergeType::TTLRecompress:next_recompress_ttl_merge_times_by_partition[partition_id] = current_time + (*settings)[MergeTreeSetting::merge_with_recompression_ttl_timeout];return;}
}

选择part去merge的调用栈:

chooseMergeFrom()        ->

        MergeSelectorApplier::chooseMergeFrom()        ->

                if 如果有TTL...  then tryChooseTTLMerge()        ->

                        ITTLMergeSelector::select()       ->

                                ITTLMergeSelector::findCenter()

判断位置,是否推迟的逻辑关键函数为needToPostponePartition:

std::optional<ITTLMergeSelector::CenterPosition> ITTLMergeSelector::findCenter(const PartsRanges & parts_ranges) const

{

    assert(!parts_ranges.empty());

    std::optional<CenterPosition> position = std::nullopt;

    for (auto range = parts_ranges.begin(); range != parts_ranges.end(); ++range)

    {

        assert(!range->empty());

        const auto & range_partition = range->front().info.getPartitionId();

        if (needToPostponePartition(range_partition))

            continue;

        for (auto part = range->begin(); part != range->end(); ++part)

        {

            if (!canConsiderPart(*part))

                continue;

            time_t ttl = getTTLForPart(*part);

            if (!ttl || ttl > current_time)

                continue;

            if (!position || ttl < getTTLForPart(*position->center))

                position.emplace(range, part);

        }

    }

    return position;

}

needToPostponePartition内部逻辑为:

bool ITTLMergeSelector::needToPostponePartition(const std::string & partition_id) const

{

    if (auto it = merge_due_times.find(partition_id); it != merge_due_times.end())

        return it->second > current_time;

   

    return false;

}

而这个merge_due_times就是每次merge完之后的调整的next_delete_ttl_merge_times_by_partition。

最后附上TTL执行的部分调用栈:

TODO:调小merge_with_ttl_timeout,验证。

第二种情况: 有ttl_only_drop_parts配置

如果配置了这个参数,ck并不会在某个part中的部分数据达到过期时间时,进行过期数据的删除。而是整个part的数据都达到过期时间时才会进行删除(这里的删除并不是物理删除,而是逻辑上的删除,即将这个part标记为inactive,对应system.parts关于这个part的记录的active字段为0)。

之后MergeTree / ReplicatedMergeTree 的cleanup线程会进行删除(这是物理删除,即删除磁盘中的文件)的动作。

由此可见,不管配没配置这个参数,ck在TTL Merge任务的时候并不会做真正删除过期数据的操作,只是逻辑删除,真正的删除交给后台cleanup线程。

核心代码位置:

执行阶段:

直接跳过:

具体的执行逻辑可以看日志:

部分日志是我手动添加日志的,例如:merge_type = XXX. 这部分。

TODO: 设置system.parts的active字段为0的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87005.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementui修改radio字体的颜色和圆圈的样式

改完 <div class"choose"><el-radio-group v-model"radioNum"><el-radio label"1" size"large">Option 1</el-radio><el-radio label"2" size"large">Option 2</el-radio>&l…

力扣3381. 长度可被 K 整除的子数组的最大元素和

由于数据范围是2*10^5所以必然是遍历一次&#xff0c;子数组必定要用到前缀和&#xff0c;之前的题目中总是遇到的是子数组的和能不能被k整除&#xff0c;而这里不一样的是子数组的长度能不能被k整除&#xff0c;如果单纯的枚举长度必定超时&#xff0c;而看看题解得出的思路&a…

基于SSM的勤工助学系统的设计与实现

第1章 摘要 基于SSM框架的勤工助学系统旨在为学生、用工部门和管理员提供高效便捷的管理平台。系统包括学生端、用工部门端和管理员端&#xff0c;涵盖了从岗位发布、申请审核、工时记录、薪资管理到数据统计等完整的功能需求。 学生可以通过系统首页浏览最新的岗位信息和公告&…

2025年06月30日Github流行趋势

项目名称&#xff1a;twenty 项目地址 URL&#xff1a;https://github.com/twentyhq/twenty项目语言&#xff1a;TypeScript历史 star 数&#xff1a;31,774今日 star 数&#xff1a;1,002项目维护者&#xff1a;charlesBochet, lucasbordeau, FelixMalfait, Weiko, bosiraphae…

creo 2.0学习笔记

Creo软件从入门到精通——杜书森 1.1 Creo基本建模过程介绍 新建-零件-改名称-取消使用默认模板&#xff0c;是因为默认的是英制尺寸&#xff0c;自定义可选择mmns_part_solid&#xff0c;模板主要是设置模型的单位拉伸-选取FRONT-点击草绘视图&#xff0c;可进行草绘旋转——…

ZNS初步认识—GPT

1. ZNS SSD 的基本概念 Zoned Namespace (ZNS): ZNS 是一种新的NVMe接口规范&#xff0c;它将SSD的逻辑块地址空间划分为多个独立的、固定大小的“区域”&#xff08;Zones&#xff09;。区域 (Zone): ZNS SSD 的基本管理单元。每个区域都有自己的写入指针&#xff08;write p…

【seismic unix生成可执行文件-sh文件】

Shell脚本文件&#xff08;.sh文件&#xff09;简介 Shell脚本文件&#xff08;通常以.sh为扩展名&#xff09;是一种包含Shell命令的文本文件&#xff0c;用于在Unix/Linux系统中自动化执行任务。它由Shell解释器&#xff08;如Bash、Zsh等&#xff09;逐行执行&#xff0c;常…

Debezium日常分享系列之:在 Kubernetes 上部署 Debezium

Debezium日常分享系列之&#xff1a;在 Kubernetes 上部署 Debezium 先决条件步骤部署数据源 (MySQL)登录 MySQL db将数据插入其中部署 Kafka部署 kafdrop部署 Debezium 连接器创建 Debezium 连接器 Debezium 可以无缝部署在 Kubernetes&#xff08;一个用于容器编排的开源平台…

利润才是机器视觉企业的的“稳定器”,机器视觉企业的利润 = (规模经济 + 技术差异化 × 场景价值) - 竞争强度

影响机器视觉企业盈利能力的关键因素。这个公式本质上反映了行业的核心动态:利润来自成本控制(规模化效应)和差异化优势(技术壁垒与场景稀缺性的协同),但被市场竞争(内卷程度)所侵蚀。下面我将一步步拆解这个公式,结合机器视觉行业的特点(如工业自动化、质检、安防、…

EPLAN 中定制 自己的- A3 图框的详细指南(一)

EPLAN 中定制 BIEM - A3 图框的详细指南 在智能电气设计领域&#xff0c;图框作为图纸的重要组成部分&#xff0c;其定制的规范性和准确性至关重要。本文将以北京经济管理职业学院人工智能学院的相关任务为例&#xff0c;详细介绍在 EPLAN 软件中定制 BIEM - A3 图框的全过程…

macbook开发环境的配置记录

前言&#xff1a;好多东西不记录就会忘记 git ssh配置 当我们的没有配置git ssh的时候&#xff0c;使用ssh下载的时候会显示报错“make sure you have the correct access rights and respository exits" 如何解决&#xff0c;我们先在命令行检查检查一下用户名和邮箱是…

GitLab 18.1 高级 SAST 已支持 PHP,可升级体验!

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

[学习]M-QAM的数学原理与调制解调原理详解(仿真示例)

M-QAM的数学原理与调制解调原理详解 QAM&#xff08;正交幅度调制&#xff09;作为现代数字通信的核心技术&#xff0c;其数学原理和实现方法值得深入探讨。本文将分为数学原理、调制解调原理和实现要点三个部分进行系统阐述。 文章目录 M-QAM的数学原理与调制解调原理详解一、…

图书管理系统练习项目源码-前后端分离-使用node.js来做后端开发

前端学习了这么久了&#xff0c;node.js 也有了一定的了解&#xff0c;知道使用node也可以来开发后端&#xff0c;今天给大家分享 使用node 来做后端&#xff0c;vue来写前端&#xff0c;做一个简单的图书管理系统。我们在刚开始学习编程的时候&#xff0c;需要自己写大量的项目…

【甲方安全视角】企业建设下的安全运营

文章目录 一、安全运营的概念与起源二、安全运营的职责与定位三、安全运营工程师的核心能力要求四、安全运营的典型场景与应对技巧1. 明确责任划分,避免“医生做保姆”2. 推动机制:自下而上 vs. 自上而下3. 宣传与内部影响力建设五、安全运营的战略意义六、为何需要安全原因在…

03认证原理自定义认证添加认证验证码

目录 大纲 一、自定义资源权限规则 二、自定义登录界面 三、自定义登录成功处理 四、显示登录失败信息 五、自定义登录失败处理 六、注销登录 七、登录用户数据获取 1. SecurityContextHolder 2. SecurityContextHolderStrategy 3. 代码中获取认证之后用户数据 4. 多…

IPLOOK 2025上半年足迹回顾:连接全球,步履不停

2025年上半年&#xff0c;IPLOOK积极活跃于全球通信舞台&#xff0c;足迹横跨亚洲、欧洲、非洲与北美洲&#xff0c;我们围绕5G核心网、私有网络、云化架构等方向&#xff0c;向来自不同地区的客户与合作伙伴展示了领先的端到端解决方案&#xff0c;深入了解各地市场需求与技术…

【Kafka】docker 中配置带 Kerberos 认证的 Kafka 环境(全过程)

1. 准备 docker 下载镜像 docker pull centos/systemd&#xff0c;该镜像是基于 centos7 增加了 systemd 的功能&#xff0c;可以更方便启动后台服务 启动镜像 使用 systemd 功能需要权限&#xff0c;如果是模拟 gitlab services 就不要使用 systemd 的方式启动 如果不使用 s…

用Python构建一个可扩展的多网盘聚合管理工具 (以阿里云盘为例)

摘要 本文旨在从开发者视角&#xff0c;探讨并实践如何构建一个命令行界面的、支持多网盘聚合管理的工具。我们将以阿里云盘为例&#xff0c;深入解析其API认证与核心操作&#xff0c;并用Python从零开始实现文件列表、重命名、分享等功能。更重要的是&#xff0c;本文将重点讨…

筑牢网络安全屏障

在数字化浪潮席卷全球的今天&#xff0c;网络空间已成为继陆、海、空、天之后的 “第五疆域”&#xff0c;深刻影响着国家政治、经济、军事等各个领域。“没有网络安全就没有国家安全”&#xff0c;这句论断精准道出了网络安全与国家安全之间密不可分的关系。​ 网络安全关乎国…