ClickHouse v22.8.18.31-lts 版本解读:FINAL 查询性能优化与多类关键缺陷修复
2026/9/14 8:23:36 网站建设 项目流程

ClickHouse v22.8.18.31-lts 版本解读:FINAL 查询性能优化与多类关键缺陷修复

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

本篇围绕 ClickHouse 官方变更记录docs/changelogs/archive/v22.8.18.31-lts.md展开,逐条解读 v22.8.18.31-lts(提交 4de7a95a544)相对上一版 v22.8.17.17-lts(提交 df7f2ef0b41)引入的性能改进、缺陷修复与构建改进。读完本文,你能理解每个修复对应的 ClickHouse 内部机制——MergeTree 的 FINAL 读取、短路(short-circuit)函数执行、JIT 编译、Keeper 协调服务等——并结合当前仓库中的源码定位,判断这些修复对你线上 22.8 LTS 分支升级的实际影响。

版本定位与变更记录结构

该变更日志属于 ClickHouse 的 LTS(长期支持)分支 22.8 的维护性补丁发布。文件头部的 "FIXME as compared to" 是 ClickHouse 自动 changelog 工具的固定表述,含义是"本版本相对于上一版本的差异"。从 下一个 LTS 版本的变更记录 可以看到,v22.8.19.10-lts 正是以 v22.8.18.31-lts(4de7a95a544)为基准生成的,印证了 22.8 分支按此顺序迭代。

本次发布包含四类内容,全部继承自原文档的分组:

分类条目数典型条目
Performance Improvement1FINAL 查询过度读取修复(回溯自 master 的 PR #49214)
Build/Testing/Packaging Improvement1时区数据库更新(PR #48572)
Bug Fix8LowCardinality 短路执行错误转换、multiIf 崩溃、Log 表族截断后行数错误等
NOT FOR CHANGELOG / INSIGNIFICANT3测试报告改进、子模块更新、构建中捕获 dockerd 异常

性能改进:修复 FINAL 查询中的过度读取

本次唯一的性能改进条目是:

Backported in #49214: Fixed excessive reading in queries withFINAL. #47801 (Nikita Taranov)

这说明该修复最初针对 master 分支开发(PR #47801),随后通过回溯(backport,回溯跟踪任务 #49214)进入 22.8 LTS 分支。

FINAL是 MergeTree 家族表引擎处理"去重"的关键特性:当表使用ReplacingMergeTreeCollapsingMergeTree等按ORDER BY键保留多行、依赖后台 merge 最终收敛的语义时,SELECT ... FROM t FINAL会在查询阶段同步完成去重,而不是把收敛工作留给后台合并。去重意味着同一个 key 可能散落在多个数据部分(part)中,引擎需要跨 part 读取并关联这些行;如果读取规划不当,就会读出远多于最终结果所需的行与列,造成 CPU 和 IO 放大。

从当前仓库的源码结构看,MergeTree 的读取任务生成与 FINAL 语义相关逻辑集中在 MergeTree 存储实现 中,其中还包含OPTIMIZE FINAL等待正在执行的 merge 的超时控制等逻辑。该修复正是作用于这条读取路径,使 FINAL 查询只读取必要的行,对高基数去重表、且依赖 FINAL 出正确结果的分析查询(如监控指标取最新值)收益明显。

构建与打包改进:时区数据库批量更新

Update time zones. #48572 (Alexey Milovidov)

ClickHouse 内置 IANA 时区数据库,供toTimeZonetimezone类函数与 DateTime 类型按命名时区做偏移换算。本条目一次性更新了 25 个时区定义,覆盖:

  • 非洲/中东:Africa/Cairo、Africa/Casablanca、Africa/El_Aaiun、Asia/Gaza、Asia/Hebron、Egypt;
  • 美洲(含加拿大、墨西哥、美国属地):America/Bogota、America/Cambridge_Bay、America/Ciudad_Juarez、America/Godthab、America/Inuvik、America/Iqaluit、America/Nuuk、America/Ojinaga、America/Pangnirtung、America/Rankin_Inlet、America/Resolute、America/Whitehorse、America/Yellowknife、Canada/Yukon;
  • 亚洲:Asia/Kuala_Lumpur、Asia/Singapore、Singapore;
  • 欧洲:Europe/Kirov、Europe/Volgograd。

这类更新通常对应 IANA 发布的夏令时/政治性偏移调整。对 22.8 LTS 用户的实际意义在于:升级后跨上述时区的toTimeZone()换算、带时区存储与展示结果将与 IANA 最新数据一致;如果你的业务依赖历史偏移做对账,应关注升级前后结果的差异窗口。

缺陷修复详解

修复 LowCardinality 列在短路函数执行中的错误转换(PR #43311)

Fix bad cast from LowCardinality column when using short circuit function execution (Kruglov Pavel)

ClickHouse 的短路(short-circuit)执行机制允许ifmultiIf等函数按条件逐行取分支,从而避免对未选中分支的列做无谓计算。该机制对低基数列(LowCardinality,即带字典编码的 Nullable/String 等类型)有特殊的类型处理路径:需要从字典列中抽取满足条件的值再还原。本修复纠正了这条路径上的错误转换(bad cast),即特定组合下从 LowCardinality 列取值时产生了不正确的类型转换,可能表现为结果错误或异常。

仓库源码可以看到短路机制的函数级开关:每个函数通过isSuitableForShortCircuitArgumentsExecution声明自己是否适合参与短路执行。例如 randomStringUTF8 函数实现 第 58 行明确声明自己不适合短路参数执行:

bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }

这类"白名单/黑名单"判断与 LowCardinality 的类型包装共同构成了短路执行的正确性边界,本修复属于该机制在类型处理细节上的补漏。

修复 randomStringUTF8(奇数长度) 的 MSan 问题(PR #49750)

Fix msan issue in randomStringUTF8(<uneven number>) (Robert Schulze)

randomStringUTF8(n)生成包含 n 个 Unicode 码点的随机 UTF-8 字符串。从 其实现源码 可以看到,函数先按码点累计长度并做总量上限保护(单次调用总码点数不得超过1ULL << 29),再逐行生成 UTF-8 编码字节。当 n 不是 2 的整数倍(uneven number)时,字符串在 8 字节 SIMD 对齐缓冲上的尾数处理存在未初始化内存访问,被 MemorySanitizer(MSan)检出。MSan 类问题在生产中不必然表现为错误结果,但说明曾读到未初始化字节,属于必须修复的内存安全缺陷。

修复 JIT 编译下不等号对 NaN 的比较语义(PR #50056)

JIT compilation not equals NaN fix (Maksim Kita)

ClickHouse 可对表达式生成 LLVM JIT 机器码。在 x86 浮点指令集中,"不等"(!=)与"小于或大于"(<>的语义分支)对 NaN 的处理存在微妙差异:部分实现下a != b对 NaN 的行为与 SQL 三值逻辑期望不一致。本修复保证 JIT 编译路径与解释执行路径对!=涉及 NaN 输入时结果一致,避免开启 JIT 后数值比较结果出现不可预期的分支。

修复 multiIf 常量条件 + Nullable 参数导致的崩溃(PR #50123)

Fix crash withmultiIfand constant condition and nullable arguments (Anton Popov)

multiIf(cond_1, then_1, ..., else)是 ClickHouse 对if的多分支泛化。从 multiIf 的实现源码 可以看到:FunctionMultiIf继承自FunctionIfBase,其isShortCircuit(第 80–86 行)配置了惰性执行策略——第一个条件参数禁用惰性求值,其余公共子树在参数数不为 3 时启用惰性执行;同时它对 Nullable 分支有专门处理(getArgumentsThatDontImplyNullableReturnType收集所有条件参数)。当某个条件为常量(例如multiIf(1, col_nullable, ...))且分支为 Nullable 时,短路执行与常量折叠的组合路径曾触发崩溃,本修复补上了这条边界路径。

修复 DateTime64 索引查询中 Date/Date32 到 DateTime64 的类型转换(PR #50280)

Fixed type conversion from Date/Date32 to DateTime64 when querying with DateTime64 index (Lucas Chang)

该修复涉及DateTime64列上的跳数索引(sparse index):当索引键是 DateTime64、而查询条件使用 Date/Date32 字面量或列参与比较时,索引谓词的标记计算(mark 定位)依赖两侧类型的正确换算。此前 Date/Date32 到 DateTime64 的转换处理不当,可能导致索引过滤错误(漏行或错误缩小扫描范围)。对以 DateTime64 作主键列、常用日期范围过滤的表,此项修复直接关系到索引剪枝的正确性。

修复 Keeper 预处理请求异常时的死锁(PR #50387)

Fix Keeper deadlock on exception when preprocessing requests. (frinkr)

ClickHouse Keeper 是内置的类 ZooKeeper 协调服务,其服务端实现位于 Coordination 模块 中,启动入口见 keeper 程序目录。"预处理请求"(preprocessing)指正式执行前的会话检查、ACL 校验、操作合法性检查等阶段。修复前,一旦预处理阶段抛出异常(例如会话过期、参数非法),某些代码路径会在清理过程中重复获取锁,导致线程死锁——即一个错误请求可能把 Keeper 服务拖死,影响同实例上所有依赖协调的分布式表与复制引擎。该修复对以 Keeper 做集群协调的部署属于高优先级稳定性修复。

修复 Log 表族 TRUNCATE 后返回错误行数(PR #50585)

Fix Log family table return wrong rows count after truncate (flynn)

StorageLog是 ClickHouse 面向日志采集场景的轻量引擎(TableLogURLLogNodeLog等表引擎的基类),实现位于 StorageLog.cpp。该类引擎的行数统计维护在内存元信息中;此前执行TRUNCATE TABLE后行数元信息未同步刷新,导致system.tables/system.parts等视图或元数据接口返回错误的行数。修复后行数与实际数据保持一致,避免基于行数的调度与告警逻辑误判。

避免 GLOBAL JOIN 右表读取全部列(PR #50721)

Do not read all the columns from right GLOBAL JOIN table. (Nikolai Kochetov)

GLOBAL JOIN是 ClickHouse 在分布式查询下处理右表无法被本地分片过滤时的执行方式:右表整表(或整分区)传输到各左表所在节点再执行连接。本修复让右表只读取连接实际用到的列,而不是全部列,直接减少 GLOBAL JOIN 场景的网络传输与反序列化开销。对跨集群/跨分片大表关联、右表宽表(列多但连接只用少数键列)的查询收益明显。

其他(不进入正式 changelog)

原文档最后列出了三条 "NOT FOR CHANGELOG / INSIGNIFICANT" 条目,均为工程侧改进,对用户不可见:

  • 改进测试报告(PR #49151,Mikhail f. Shiryaev);
  • 更新 dockerdistribution相关依赖(PR #50114,Mikhail f. Shiryaev);
  • 在构建流程中捕获 dockerd 异常(PR #50700,Mikhail f. Shiryaev)。

这些条目集中出现于 CI/构建基础设施维护,可作为观察该分支工程活动状态的参考。

升级建议与延伸阅读

综合本次发布的条目分布,可以得出以下针对 22.8 LTS 分支的判断:

  1. 强烈建议升级:如果你使用 Keeper 做协调服务(有分布式表、Replicated 引擎),PR #50387 的死锁修复是稳定性刚需;
  2. 值得升级:大量使用FINALGLOBAL JOINDateTime64索引或multiIf的查询负载,可在正确性与性能两方面获益;
  3. 关注点:时区数据库批量更新会影响上述 25 个时区的偏移计算结果,升级前后应对跨时区报表做一次抽样比对。

变更记录的完整原始文本见 v22.8.18.31-lts 变更日志;如需追踪前后版本差异,可对照 v22.8.19.10-lts 变更日志,其 diff 基准正是本版本。文中涉及的源码入口(MergeTree 存储、multiIf 函数、randomStringUTF8 函数、Log 引擎)均可在当前仓库中直接查阅,便于进一步核对实现细节。

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询