ClickHouse v26.7.2.59-stable 版本解析:AI 函数链路标记、TopK 查询条件缓存与一批高价值修复
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
本指南以 ClickHouse 官方版本记录 v26.7.2.59-stable 变更日志(对比基线 v26.7.1.1315-stable)为核心,逐项拆解该稳定版的实验性特性、性能改进、功能增强与全部用户可见的 Bug 修复,并结合当前仓库源码说明各配置项的实际位置、默认值与底层实现。读完本文,你将掌握该版本引入的新设置(如jemalloc_merge_tree_arenas、use_query_condition_cache_for_top_k)的用法与适用场景,并能按类别快速定位修复内容对自身业务的影响面。
版本概览与基线说明
本次发布号为v26.7.2.59-stable(提交1399e12824d),是一个基于26.7分支的稳定版维护发布,其变更对比基线为v26.7.1.1315-stable(提交a6156303df6)。变更内容全部通过 Backport 机制合入,即每个条目都先在主分支(master)合并,再由发布团队挑选回移植到 26.7 稳定分支,这一点在变更日志中体现为每条记录均标注Backported in #xxxxx的关联 issue 编号。
从变更结构看,本次发布主要集中在四类:
- Experimental Feature(实验性特性):1 项;
- Performance Improvement(性能改进):2 项;
- Improvement(功能改进):7 项;
- Bug Fix(用户可见缺陷修复):30+ 项,涵盖崩溃、数据正确性、数据丢失、安全信息泄露等严重问题;
- Build/Testing/Packaging Improvement(构建与打包改进):2 项依赖升级。
实验性特性:AI 函数 HTTP 请求的上游端点标记
本次发布的唯一实验性特性与 AI 函数相关:为OpenAI 格式的 HTTP 请求添加 SQL 层面的标记(tag),标记内容为调用该请求的 AI 函数的 SQL 名称,用于上游端点(upstream endpoint)的请求识别与计费/审计分析(PR #110449)。
该功能的价值在于:当通过 ClickHouse 的 AI 相关表函数或函数(如调用外部 LLM/embedding 服务的场景)向 OpenAI 兼容端点发起请求时,服务端可以把流量精确归属到具体的 SQL 函数,便于在上游做用量统计与链路追踪。这属于实验性能力,使用前应关注后续版本的行为演进。
性能改进
本次发布包含两项性能改进,均针对 MergeTree 家族的核心路径。
FINAL + 过滤 + 小 LIMIT 场景启用懒物化
在查询包含FINAL、过滤条件以及较小的LIMIT、且没有ORDER BY时,现在会应用懒物化(lazy materialization)优化(PR #110722)。该优化针对ReplacingMergeTree等支持FINAL的引擎生效。
背景是:FINAL语义需要逐行合并同一排序键的版本,若目标结果行数很小(受LIMIT限制),提前物化全部列会浪费大量 IO 与内存。懒物化让引擎先读取、合并足够的行达到LIMIT所需数量,再按需读取其余列,从而显著降低此类查询的资源开销。适用前提是无ORDER BY:一旦查询要求全局排序,执行计划仍需完整物化候选行,优化不生效。
异步插入跨分区去重哈希只计算一次
修复了异步插入(async insert)在跨 P 个分区刷盘时O(P×N) 的重复哈希计算问题(PR #111150)。
在旧实现中,一次插入被按分区键拆分到多个分区时,每个分区都会对整批数据重新计算去重哈希。修复后,DeduplicationInfo::prewarmDataHashes会在分区循环之前调用一次,所有分区的克隆数据都继承预计算好的data_hash_batch,不再重复计算 P 次。该改动同时作用于MergeTreeSink与ReplicatedMergeTreeSink两条写入路径,DuplicationElapsedMicroseconds度量指标会随分区数增加而成比例下降。
从源码可以看到这一实现细节:在 MergeTreeSink.cpp 中,当启用去重时先执行一次checkTimeLimit()保留原有的中断点语义,随后在ProfileEventTimeIncrement<Microseconds> duplication_elapsed计时段内调用prewarmDataHashes(),注释明确说明:filterToPartition产生的各分区信息会拷贝这些带缓存的哈希 token,因此跨多个分区的行只需哈希一次。相关行为在 gtest_async_inserts.cpp 中有对应测试覆盖。
功能改进(Improvement)
part 级 min-max 索引补齐:_block_number与_block_offset
本版修复了_block_number和_block_offset虚拟列启用 part 级 min-max 索引所剩余的问题(PR #109281)。此前该索引在部分场景下会给出错误剪枝结果,本次补齐后,针对这两个虚拟列的等值/范围过滤可以在 part 粒度直接裁剪数据,减少扫描量。
新增服务端设置jemalloc_merge_tree_arenas
为缓解多核服务器上并发 merge 之间的内存分配器锁竞争,新增服务端设置jemalloc_merge_tree_arenas(PR #109490),它控制用于MergeTreepart 与表元数据的专用 jemalloc arena:
0:禁用专用 arena;1:使用单一 arena(默认值);N:创建 per-CPU 的 arena 池。
同时,专用 arena 的使用范围被收窄为仅容纳长生命周期元数据,避免短生命周期对象挤占专用 arena。对许多核机器而言,采用 arena 池可把不同 merge 线程的分配分散到独立 arena,显著降低分配器内部的全局锁竞争。
查询条件缓存新增 TopK 开关
新增设置use_query_condition_cache_for_top_k(默认关闭),用于控制查询条件缓存(query condition cache)是否作用于ORDER BY ... LIMIT n(TopK)类查询(PR #111492 中,该设置类型为Bool,默认值为true声明,但其说明指出作为预防措施在发布时默认关闭,直到缓存条目的正确性被充分验证;同时它仅在use_query_condition_cache开启时才有意义。
值得注意的实现细节:TopK 查询在运行过程中可能依据运行阈值丢弃 granule,因此其缓存条目按 TopK 计划参数与被读取的 part 集合分区,避免不同执行形态之间错误复用缓存。
JOIN 兼容性设置analyzer_compatibility_apply_final_to_all_joined_tables
新分析器(Analyzer)在 26.6 起改变了FINAL的传播语义:此前写在 JOIN 最左侧表上的FINAL会被错误地应用到其他连接表。本版新增设置analyzer_compatibility_apply_final_to_all_joined_tables(PR #111589 中可以看到其默认值为false,说明文档明确建议:推荐做法是显式地在每个需要FINAL的表上书写FINAL,而不是依赖该兼容开关。该设置注册在设置变更历史中,因此compatibility设为 26.6 之前的版本时会自动恢复旧语义。测试用例见 04627_analyzer_compatibility_final_all_joined_tables。
命名集合存储类型可查询
命名集合(named collections)生效的存储类型现在可以通过system.server_settings中的named_collections_storage.type键查询,也可用getServerSetting('named_collections_storage_type')函数读取(PR #111806)。这为运维排查“集合到底存到本地还是 ZooKeeper”提供了标准入口。
快照生成 CPU 开销优化
针对文件数量巨大的场景,降低了生成快照时的 CPU 使用(PR #112297)。同批改动的配套调整还包括将max_snapshot_commit_thread_pool_size下调至 16,见下文“非用户可见变更”一节。
Iceberg 兼容性:容忍 manifest 缺失sequence_number
Iceberg v2 规范要求 manifest 文件包含sequence_number字段,但部分引擎(如 BigQuery)写出的文件可能缺少该字段。本版允许读取这类不合规范的表(PR #112431),提升跨引擎数据互操作性。
Web UI 细节修复
修复了 Firefox 下 Web UI 中“+”(新建标签页)按钮渲染高度超过标签页本身的问题(PR #109524)。
Bug 修复详解
本版 Bug 修复数量最多,按影响面可分为几类。
崩溃类(Crash / SIGSEGV / OOB)
- Protobuf 读取崩溃:当
input_format_allow_errors_num > 0且同一 block 中有效消息位于坏(可跳过)消息之前时,会触发服务崩溃(SIGSEGV),已修复(PR #107739)。 - S3Queue / AzureQueue 越界访问:在
enable_hash_ring_filtering = 1、批次含不可处理文件且恰逢 Keeper 请求设置批次为 processing 失败时,发生越界访问崩溃,已修复(PR #108977)。 - 畸形聚合状态反序列化:反序列化含
String值的畸形聚合函数状态时发生越界访问导致段错误,现在改为校验并拒绝,不再崩溃(PR #111606)。 - macOS aarch64 栈回溯崩溃:在协程/fiber 栈上执行(如内存 profiler 触发)栈回溯时崩溃,已修复(PR #111656)。
- 加密磁盘 Compact part 直接 IO 读取:
ReadBufferFromEncryptedFile: Wrong file position逻辑错误导致 merge 卡在system.replication_queue,已修复(PR #112943)。
数据正确性与数据丢失类
- 并发 RENAME COLUMN 导致数据丢失:当 merge 与
ALTER TABLE ... RENAME COLUMN并发、或某列的值仅来自 lightweightUPDATE时,无默认表达式的列可能从合并后的 part 中被删除,读取结果为 NULL。这是严重的数据丢失问题,已修复(PR #109356)。 - 反向排序键剪枝错误:对于
ORDER BY (g, r DESC)这类含降序列的排序键,跨越前导键列变化与降序列的 granule 可能被错误剪枝而丢行,已修复(PR #111059)。 - Nullable 元数据变更后的子列误判:对列执行仅元数据的
ALTER MODIFY COLUMN T改为Nullable(T)后,旧 part 的.null子列从存储类型默认值(NULL)填充而非从实际父列推导,导致IS NULL/IS NOT NULL/count()在optimize_functions_to_subcolumns下结果错误,已修复(PR #110584。 - 文本索引下空 needle 函数结果错误:
has、mapContainsKey、mapContainsValue在存在文本索引时对空 needle 返回错误结果,已修复(PR #110246)。 - Bucketed Map 序列化键序:保留 bucketed Map 序列化的原始键顺序,修复依赖键序的比较操作(PR #109178)。
- 物化视图 + Alias 目标 + 去重表的数据错乱:当 INSERT 流经依赖物化视图、目标为
Alias且内层查询改变行数、并在 alias 跳转后可达去重表时,触发block.rows() == getRows()逻辑错误(release 构建下表现为越界读与去重失效),已修复(PR #111103)。 - File 引擎向不可追加格式追加写入:向非空文件以不支持追加的格式(如
Avro)执行 INSERT(经由文件描述符或分区路径)会绕过既有检查,导致写入第二个文件头、文件不可读。现在统一以CANNOT_APPEND_TO_FILE拒绝(PR #112839)。 - 空 part 合并文本索引:合并含文本索引的 part 时若其中一个 part 为空(如突变删光所有行),出现
ATTEMPT_TO_READ_AFTER_EOF,已修复(PR #112490)。
查询正确性类
- LEFT JOIN 唯一右键混合 ON 条件:
JoiningTransform中LEFT JOIN使用唯一右键、混合ON条件且max_joined_block_size_rows较小时出现LOGICAL_ERROR(Invalid number of rows in Chunk),已修复(PR #106928)。 - 虚拟列 + 懒物化:
_part_starting_offset/_part_offset虚拟列用于 WHERE 且启用懒物化时出现NOT_FOUND_COLUMN_IN_BLOCK,已修复(PR #108287)。 - FINAL + PREWHERE 下推:
SELECT s FROM t FINAL WHERE k GROUP BY s在optimize_move_to_prewhere_if_final = 1(该设置定义见 Settings.cpp)时,若过滤排序键列不在 SELECT 列表且被移到 PREWHERE,出现NOT_FOUND_COLUMN_IN_BLOCK,已修复(PR #111721)。 - ANY JOIN 到 Join 引擎表:当 WHERE 中右表列过滤使规划器可将 ANY 连接改写为 SEMI/ANTI 时,
Join引擎表(固定声明 strictness)出现INCOMPATIBLE_TYPE_OF_JOIN,现在对这类表拒绝改写(PR #111362)。 - CTE 限定列名:启用分析器时,视图内存储的查询使用
cte_name.column限定列名会报UNKNOWN_IDENTIFIER,已修复(PR #111386)。 - 字典 JOIN 键类型归一化:JOIN 到字典时使用
Nullable、LowCardinality或LowCardinality(Nullable)连接键而字典键未包裹,报TYPE_MISMATCH;现在直接字典查找会将键归一化为字典声明键类型(与dictGet/dictHas一致),且 NULL 键永不匹配(PR #111857)。 - JOIN ON 条件在 WHERE 中重复:
join_use_nulls = 1时重复JOIN ON条件于 WHERE 报AMBIGUOUS_COLUMN_NAME(Block structure mismatch),已修复(PR #112007)。 - materialized view 行数变化 + 去重:修复
block.rows() == getRows()逻辑错误(见上文数据正确性部分)。
对象存储与数据湖类
- 只读对象存储副本不发现新 part:配置
read_only = true的磁盘无法通过refresh_parts_interval发现新 part,且table_disk = true被误拒("table_disk is not supported for non-ObjectStorage disks"),已修复(PR #110460)。 - S3Queue/AzureQueue ordered 模式锁续期:持久化处理节点(persistent processing nodes)模式下,流式处理期间现在会刷新 bucket 锁,避免 TTL 清理(
persistent_processing_node_ttl_seconds)移除活跃处理器的锁;若锁所有权仍丢失,会被检测并上报(逻辑错误 +ObjectStorageQueueBucketLockLost相关 profile event),流式处理以全新文件迭代器恢复(PR #110292)。 - Iceberg 类型字符串空白差异:读取 decimal 等参数化原始类型在不同元数据文件中序列化空白不同的 Iceberg 表时误报
ICEBERG_SPECIFICATION_VIOLATION(如decimal(20,0)vsdecimal(20, 0)),现在比较时忽略空白(PR #109676)。 - Iceberg OPTIMIZE MANIFEST:当 manifest 分区元组与其分区规范不匹配时
OPTIMIZE TABLE ... MANIFEST失败,已修复(PR #111368)。 - Paimon 可变 LATEST 提示并发替换:读取 Paimon 表时 mutable
snapshot/LATEST提示被并发替换可能导致失败,现在无效或过期提示安全回退到快照列表(PR #112010)。 - S3 显式 role 的 STS 授权:
s3_allow_server_credentials_in_user_queries错误拒绝查询中提供的extra_credentials(role_arn = '...');现在显式 role 的 STS assume-role 始终允许(不暴露服务端自身凭据,是授予私有 S3 桶访问权的文档化方式)(PR #112603)。
安全与凭据泄露修复(重点)
本版进行了一次大范围凭据泄露修复(PR #109768),覆盖SHOW CREATE、system.query_log、服务端日志与EXPLAIN输出。修复范围包括:
S3定位器的所有形式现在都会掩蔽session_token与 Google ADC secrets;extra_credentials/headers的值在任意参数位置都会被掩蔽;- 重复或表达式形式的 secret key、非法位置形式(fail closed)、嵌入 S3 URL 中的凭据同样被掩蔽;
- 覆盖对象:显式 URL 与命名集合的
s3/s3Cluster表函数、S3 系表引擎(S3、GCS、数据湖引擎、S3Queue)、S3数据库引擎、BACKUP ... TO S3以及Backup数据库引擎; - 此外,由表达式构建(包括从 SQL UDF 内联)的
encrypt/decrypt/ HMAC 的 secret 参数,现在会在 projection 名称、EXPLAIN QUERY TREE与EXPLAIN actions中被隐藏。
该修复对生产安全至关重要:即使查询被记录或解释,敏感凭据也不会落入日志与系统表。
其他修复
- 路径校验:修复对
user_files的路径检查,并将本地对象访问限制仅限 user files 路径(PR #111442、PR #111483)。 _partition_id占位符兼容:文件类引擎(S3、AzureBlobStorage、URL等)路径中的{_partition_id}在未显式指定partition_strategy时重新隐含wildcard策略,不再受file_like_engine_default_partition_strategy影响,恢复 26.6 之前 DDL 的向后兼容(此前会报BAD_ARGUMENTS)。该默认策略设置的当前默认值为HIVE,见 Settings.cpp(PR #111279)。- 带参数的突变分区:
ALTER TABLE ... UPDATE/DELETE ... IN PARTITION {param:Type}的替换分区值序列化后无法回读,破坏表加载(复制表上为每个副本);现在 mutation 命令在写入 ZooKeeper 或磁盘前会验证可回读,不匹配时直接使 ALTER 失败(PR #111518)。 - 字典 CREATE OR REPLACE 残留:不同种类的字典对象执行
CREATE OR REPLACE在提交后才失败,残留_tmp_replace_*孤儿表,已修复(PR #111142)。 - TLS 对端证书内存泄漏:开启证书校验时每次 TLS 握手泄漏对端证书(
SecureSocketImpl::verifyPeerCertificateImpl未释放SSL_get1_peer_certificate返回的证书),已修复(PR #111425)。 - system.zookeeper_info 解析溢出:修复解析时的溢出问题(PR #111629)。
- macOS 采样 profiler 死锁:
pthread_rwlock在采样查询 profiler 开启时丢失唤醒导致永久挂起(Apple bug FB24027930),Darwin 上已替换为信号安全实现(PR #112267)。 - Azure HTTP Content-Length:Poco 版 Azure HTTP 传输现在为 SDK 客户端(如 Azure Key Vault)从请求体设置
Content-Length,修复411 Length Required错误(PR #110299)。 - 复杂 schema 演进拼写错误:修复复杂 schema 演进中的拼写错误(PR #111489)。
- schema 演进中的 URL 修复:PR #112165 对应修复(PR #111785)。
构建、测试与打包改进
- Apache Thrift升级至0.24.0(PR #111278)。
- SQLite amalgamation从 3.41.2 升级至3.53.4(PR #112599)。
非用户可见变更速览
除上述用户可见条目外,本版还包含若干内部变更(NOT FOR CHANGELOG / INSIGNIFICANT),供关注实现细节的读者参考:
- ZXC codec 标记为实验性(PR #111007);
- 元数据事务移除前置条件(preconditions),改为在提交时验证(PR #111353);
max_snapshot_commit_thread_pool_size下调至 16(PR #111417);- 若干测试稳定性修复与 TSan 运行时抑制(如 test_replicated_table_structure_alter、test_s3_table_functions_timeouts)。
升级与验证建议
综合本版变更,若你在生产环境使用 26.7 分支,建议重点关注以下升级验证项:
- 安全修复优先验证:凭据掩蔽覆盖了
SHOW CREATE、system.query_log与 EXPLAIN 输出,升级后可用含extra_credentials/session_token的 S3 查询验证日志与系统表中不再出现明文凭据; - 数据正确性修复影响面:并发
RENAME COLUMN+ merge、lightweight UPDATE 列的合并、optimize_functions_to_subcolumns下的 Nullable 元数据变更等修复涉及既有数据,建议对相关表执行CHECK TABLE或抽样核对; - TopK 缓存行为:
use_query_condition_cache_for_top_k默认关闭,依赖查询条件缓存加速 TopK 查询的负载需显式开启并观察缓存命中与结果一致性; FINAL语义变更:26.6 起FINAL不再自动传播到 JOIN 的其他表,若历史查询依赖旧行为,可通过analyzer_compatibility_apply_final_to_all_joined_tables或显式书写FINAL适配;- 多核 merge 环境:
jemalloc_merge_tree_arenas默认单 arena,多核高并发 merge 场景可尝试 per-CPU 池并观察内存与延迟指标。
以上全部条目的权威出处为仓库内的 v26.7.2.59-stable 变更日志,文中涉及的设置定义与实现证据分别位于 Settings.cpp、MergeTreeSink.cpp 与对应测试目录,可进一步按需查阅。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考