ClickHouse 21.4 版本深度解析:从兼容性变更到新特性与底层原理全解读
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
导读
本文基于 ClickHouse 官方发布说明 v21.4.2.10-prestable(相对基线 v21.3.1.6185-prestable)展开,系统梳理该版本中引入的向后不兼容变更、新特性、性能改进、功能增强与 Bug 修复。文中不仅完整收录发布说明中的每一项变更,还结合本仓库源码(如 toStartOfInterval 实现、isIPAddressInRange 实现、timezoneOf 实现 等)对关键能力进行底层原理剖析。读完本文,你将掌握 21.4 版本的全部变化清单、每个新函数的用法与实现机制,以及升级前需要关注的行为差异点。
一、版本概览与升级要点
v21.4.2.10-prestable 是 ClickHouse 21.4 系列的一个预发布(prestable)版本,对比基线为 v21.3.1.6185-prestable。该版本在功能层面持续加码:围绕字典(Dictionary)体系、复制与分布式查询、日期时间函数、安全认证(Kerberos)、S3 存储与零拷贝复制等方面均有大量改动。
升级前最需要关注的是文档开篇列出的三项向后不兼容变更,它们可能导致已有查询结果或表结构语义发生变化:
system.dictionaries表中的keys列被拆分为key.names与key.types两列;cutToFirstSignificantSubdomainCustom()/firstSignificantSubdomainCustom()对自定义顶级域名列表的解析结果修正;toStartOfInterval对小时间隔的对齐基准从 Unix 纪元改为午夜零点。
下面逐项展开,并结合源码说明其影响。
二、向后不兼容变更(Backward Incompatible Change)
1. system.dictionaries 表结构调整(PR #21884)
此前system.dictionaries中以单列keys描述字典键,21.4 起被替换为独立的key.names与key.types两列;同时key.names、key.types、attribute.names、attribute.types这四列不再要求字典已加载,即字典未加载时这些元数据列也可正常读取,避免了以往因字典加载失败而无法查看元数据的问题。
该改动与字典相关的新能力(见下文"字典体系全面增强")同源,均围绕src/Dictionaries目录下的字典加载与元数据管理逻辑展开。从源码结构看,字典配置解析(DictionaryStructure)与外部加载器(ExternalLoader)在 21.4 中经历了较大重构,为异步更新、Nullable 支持等功能铺路。
2. 自定义顶级域名解析修正(PR #21946)
对于出现在自定义顶级域名列表中的 3 级以上域名,旧版本会把第三级域名误判为"第一有效子域名",导致cutToFirstSignificantSubdomainCustom()与firstSignificantSubdomainCustom()返回错误结果。21.4 起该行为被修正。
该函数的实现位于 cutToFirstSignificantSubdomainCustom.cpp。注意:如果该函数被用于分片键(sharding key)等位置,修正后的结果与旧版本不一致,可能引起数据分布变化,升级后需要复核相关查询与数据路由逻辑。
3. toStartOfInterval 小时对齐改为午夜基准(PR #22060)
这是 21.4 最典型的"行为修正型"变更。旧版本中toStartOfInterval(x, INTERVAL N HOUR)的小时间隔从 Unix 纪元(1970-01-01 00:00:00)开始对齐,导致小时边界不落在自然的"整点日界"上。21.4 起小时间隔总是从当天午夜 00:00:00 对齐。
以文档给出的例子:toStartOfInterval(x, INTERVAL 11 HOUR)会把每一天切分为三个区间:
00:00:00 ~ 10:59:5911:00:00 ~ 21:59:5922:00:00 ~ 23:59:59
该行为更贴合实际业务习惯(如按天划分班次、报表时段)。从 toStartOfInterval.cpp 的源码可以看到,小时取整通过DateLUTImpl::hourIntervalModularDivisor()判断是否为"模除式取整"(即从午夜对齐的时区),若是则走 libdivide 快速路径(tryExecuteArithmeticRounding,注释中说明比通用循环快约 5 倍),否则回退到ToStartOfInterval<Hour>::execute的通用 LUT 计算。源码注释同时明确:
hour intervals are special: the calculation is always performed relative to 00:00:00 (midnight) of the current day. As a result, only hour values between 1 and 23 are useful.
即小时区间数值只对 1~23 有意义。此外该函数在 21.4 中还作为 TimescaleDBtime_bucket()与 PostgreSQLdate_bin()的别名注册(registerAlias("time_bucket", ...)、registerAlias("date_bin", ...),不区分大小写),第二个重载(带origin参数)即模拟这两种外部数据库的时间桶行为。
三、新特性(New Feature)详解
1. DateTime64 范围扩展与 DateTime 零值增强(PR #9404)
21.4 将DateTime64的可表示日期范围扩展至1925 年到 2283 年,并改进了DateTime在零日期(1970-01-01)附近的支持。这为历史数据处理(如长周期的金融、气象数据)与跨时区极端场景提供了更宽的合法区间。
2. Kerberos 认证(GSS-SPNEGO)(PR #14995)
新增对预配置用户与HTTP 请求的 Kerberos 认证支持(GSS-SPNEGO 机制)。该特性使 ClickHouse 能够接入既有的企业级 Kerberos 认证体系,适用于大规模内部部署场景下的统一身份认证,无需为每个用户单独维护口令。
3. ReplicatedMergeTree 基于 S3 的零拷贝复制(PR #16240)
这是 21.4 的重要存储能力之一:ReplicatedMergeTree表引擎在S3 存储上支持零拷贝复制(Zero-copy replication)。其原理是:当数据 part 已存在于共享的 S3 存储中时,副本间复制不再重复上传数据块,而只复制元数据引用,从而显著降低跨副本的数据传输成本与延迟。该版本后续还修复了混合存储(hybrid storage)场景下零拷贝复制的 Bug(PR #22378)。
4. 字典体系全面增强(多 PR 联合)
21.4 对字典的改动密度很高,可以合并理解为一次"字典能力大升级":
dictHas支持RangeHashedDictionary(PR #19816,修复 issue #6680):范围哈希字典此前无法直接判断某个键是否存在,21.4 起补齐。- 缓存类字典异步更新与 Nullable 支持(PR #20595):
ComplexKeyCache、SSDCache、SSDComplexKeyCache支持异步更新;Cache、ComplexKeyCache、SSDCache、SSDComplexKeyCache四类字典支持Nullable类型;dictGet、dictGetOrDefault支持一次获取多个属性。 - 新增
ExecutablePool字典源(PR #21321,关闭 issue #14528):在既有Executable字典源(执行外部脚本作为字典数据源)基础上增加进程池化的ExecutablePool源。对应实现位于 ExecutablePoolDictionarySource.cpp,通过维护一组可复用的外部进程来避免高频建连开销。 PolygonDictionary属性支持Nullable(PR #21890)。- 新增表函数
dictionary(PR #21910,关闭 issue #21560):用法与Dictionary表引擎等价,即dictionary('db.dict_name')可直接把字典当表查询。 dictGet/dictHas默认使用当前数据库(PR #21859,关闭 issue #21632):对通过 DDL 创建的字典,未显式指定库名时自动解析为当前数据库,减少跨库歧义。- 回退一项哈希字典加载优化(PR #21948):为避免大幅内存增长,回退了 PR #15454,保证外部哈希字典加载的内存占用稳定。
5. JOIN 支持隐式键类型转换(PR #19885)
21.4 起,JOIN的关联键允许隐式类型转换(关闭 issue #18567)。此前 JOIN 键两侧类型不一致会直接报错,现在引擎会尝试做兼容转换,降低跨类型关联的编码成本。同时该版本修复了JOIN ... TOTALS与arrayJoin组合时的Invalid number of rows in Chunk错误(PR #22129),并修复 partial merge join 中LowCardinality的 Bug(PR #22510)。
6. 新函数 isIPAddressInRange(PR #21329)
新增网络地址判定函数:
isIPAddressInRange(address, prefix)用于判断 IPv4 或 IPv6 地址是否落在给定的CIDR 网络前缀内,返回UInt8(1 命中 / 0 未命中)。从 isIPAddressInRange.cpp 源码(函数文档标注 IntroducedIn = {21, 4},与本文版本一致)可以看到其实现要点:
- 第一个参数支持
String、IPv4、IPv6及对应的Nullable包装; - 第二个参数必须是
String,内部通过parseIPWithCIDR()解析地址/前缀形式,并用std::from_chars校验前缀位数的合法性(IPv4 最大 32,IPv6 最大 128); - 判定逻辑在 Common/IPv6ToBinary.h 提供的
matchIPv4Subnet/matchIPv6Subnet基础上完成;地址与 CIDR 的 IP 版本不匹配时直接返回 0。
官方文档示例:
SELECT isIPAddressInRange('127.0.0.1', '127.0.0.0/8'); -- 1 SELECT isIPAddressInRange('127.0.0.1', 'ffff::/16'); -- 0(版本不匹配) SELECT isIPAddressInRange('::ffff:192.168.0.1', '::ffff:192.168.0.4/128'); -- 0该函数非常适合日志分析中基于 IP 段(如内网网段、云厂商网段)做流量归属、风险分群等场景。
7. _partition_id 虚拟列与 partitionID() 函数(PR #21401)
21.4 为MergeTree*系列表引擎新增虚拟列_partition_id,允许在查询中直接以_partition_id进行分区裁剪;同时新增partitionID()函数用于计算某个分区表达式的分区 ID 字符串。
从源码看,_partition_id的获取与分区计算逻辑位于 MergeTreePartInfo.h、MergeTreeData.cpp 等 MergeTree 存储核心文件中。该能力的实战价值在于:
SELECT count() FROM my_table WHERE _partition_id = '202104';相比传统的"按分区键条件过滤",直接按_partition_id过滤可以让优化器更早、更精确地跳过无关分区,尤其适合分区键是表达式(如toYYYYMM(date))的场景。
8. system.clusters 新增 slowdowns_count 列(PR #21480)
system.clusters表新增slowdowns_count列:当启用 hedged requests(对冲请求)时,该列记录"因某副本响应缓慢而切换到其他副本"的次数;同时errors_count列改为显示实际值。对应系统表实现在 StorageSystemClusters.cpp。配合新增的 profile eventHedgedRequestsChangeReplica(PR #21886,同时将读取数据超时单位从秒改为毫秒),DBA 可以更细粒度地观测集群副本健康度。
9. clickhouse-format 新增 --backslash 选项(PR #21494)
格式化工具clickhouse-format新增--backslash选项,可在格式化后每行末尾追加反斜杠,便于把长 SQL 拆成可粘贴到 shell 多行命令的形态:
clickhouse-format --backslash --query "SELECT * FROM t WHERE a > 1"同时(PR #21311)改进了格式化器对"最后一个查询后存在多余空格或注释"的处理,不再抛异常;并在格式化带数据的INSERT语句时提前抛出可读性更好的异常。
10. CREATE/ALTER USER 新增 GRANTEES 子句(PR #21641)
CREATE USER/ALTER USER命令新增可选的GRANTEES子句,用于限定"该用户未来可以把权限转授给哪些用户/角色",为 RBAC 权限委派提供更精细的控制面。
11. zookeeper-dump-tree 新增 ctime 选项(PR #21842)
运维工具zookeeper-dump-tree新增ctime选项,可在导出 ZooKeeper 节点树时打印节点的创建时间,便于审计与排障。
12. 新函数 timezoneOf 及函数命名一致性(PR #22001)
新增函数timezoneOf(),返回DateTime/DateTime64值的时区名称。实现位于 timezoneOf.cpp,源码中通过TimezoneMixin::getTimeZone().getTimeZone()直接从数据类型中取出时区名,并注册了timeZoneOf别名(不区分大小写):
SELECT timezoneOf(now()); -- ┌─timezoneOf(now())─┐ -- │ Etc/UTC │ -- └───────────────────┘同一 PR 还统一了函数命名:为时间/时区相关函数补齐别名timezone/timeZone、toTimezone/toTimeZone以及timezoneOf/timeZoneOf,消除历史命名不一致。
13. prefer_column_name_to_alias 设置(PR #22044)
新增设置prefer_column_name_to_alias,开启后查询中优先使用原始列名而非别名,以兼容主流数据库的别名规则(针对 issue #9715、#9887)。典型场景:当别名与列名冲突或客户端对别名解析行为与 ClickHouse 默认不同时,通过该设置获得与常见数据库一致的行为。
14. ALTER TABLE ... UNFREEZE 命令(PR #21142)
新增 SQL 命令:
ALTER TABLE table_name UNFREEZE [PARTITION 'part_expr'] WITH NAME 'backup_name';用于按备份名(可选按分区)删除此前 FREEZE 产生的备份数据,完善了基于分区的快照备份/清理闭环。
15. system.query_log 增加 query_kind 新值(PR #21102)
system.query_log的query_kind列新增Grant、Revoke、System三个取值,分别对应授权、回收权限与系统类查询,便于按查询种类审计。
16. 复制相关 HTTP 连接超时独立可配(PR #20088)
允许为复制所用的 HTTP 连接独立配置超时,不再与其他 HTTP 超时混用,避免复制链路受全局 HTTP 超时策略的干扰。
四、性能改进(Performance Improvement)
1. CSVWithNames / TSVWithNames 并行解析(PR #21149)
带表头的 CSV/TSV 格式(CSVWithNames、TSVWithNames)支持并行解析(关闭 issue #21085)。此前只有无表头变体走并行解析路径,21.4 为带表头格式补齐了并行能力,显著改善大批量导入吞吐。
2. memcpy 实现替换(PR #21520)
用更优的memcpy实现替换原有实现(关闭 issue #18583),在内存拷贝密集的路径上获得性能提升。仓库 utils/memcpy-bench 目录专门用于 memcpy 变体的基准对比,该版本还新增了若干 benchmark 变体(PR #21715、#21759)。
3. clickhouse-local 及全链路并行格式化(PR #21630)
并行格式化(parallel formatting)扩展到clickhouse-local及其他场景,大结果集的序列化输出延迟进一步降低。
4. SELECT ... FINAL ... WHERE 优化(PR #21830)
对于带FINAL的查询,允许把属于排序键的列下推到PREWHERE,减少FINAL合并阶段需要处理的数据量。
5. 小 max_rows_to_group_by 下更快的 GROUP BY(PR #21856)
当max_rows_to_group_by很小且group_by_overflow_mode='any'时,GROUP BY的执行提速——此时引擎无需维护完整的分组集合,可采用更轻量的溢出处理策略。
6. NONE 压缩编码避免不必要拷贝(PR #22145)
使用NONE编码(不压缩)时避免无谓的数据拷贝。请注意官方在该条目中明确提醒:NONE编码通常并无意义,ClickHouse 始终推荐使用压缩(默认LZ4);禁用压缩往往不会提升性能,甚至可能更差。NONE仅在两类场景下有用:数据本身不可压缩;以及合成基准测试。请勿在线上为追求"省 CPU"而盲目关闭压缩。
7. mmap 读取缓存与默认阈值调整(PR #22206 / #22326)
- PR #22206:为
min_bytes_to_use_mmap_io触发的 mmap 文件读取增加缓存,当该设置取值较小时,通过避免频繁的 mmap/munmap 调用及随之而来的缺页中断,可获得2 倍以上的性能提升。 - PR #22326:将
min_bytes_to_use_mmap_io的默认启用阈值设为64 MiB(即超过该大小的文件范围才尝试 mmap 读取),带来中等程度的性能改善。
官方文档同时提醒:mmap IO 在生产环境有显著缺陷(故障磁盘上可能 hang 或触发 SIGBUS、内存占用更不可控),更适合基准测试场景,生产环境请谨慎评估。
五、功能与易用性改进(Improvement)
1. MergeTree 新设置:min_bytes_to_rebalance_partition_over_jbod(PR #16481)
新增 MergeTree 设置min_bytes_to_rebalance_partition_over_jbod:当新 part 大小超过该阈值时,JBOD 卷上的不同磁盘会被均衡地分配新 part,缓解 JBOD 磁盘间的数据倾斜。
2. optimize_aggregation_in_order 增强(PR #19401 / #21889 / #21436)
- PR #19401:提升按排序键顺序聚合(
optimize_aggregation_in_order)的性能; - PR #21889:修复该设置开启且表内 part 较多时导致的数据欠聚合(underaggregation)Bug,并进一步小幅提升性能(后续在 issue #22625 中回迁);
- PR #21436:修复小
max_block_size下该设置的日志问题。
3. 分布式 DDL 设置增强(PR #21535)
- 设置
distributed_ddl_entry_format_version = 2可启用查询与会话设置的传播,使分布式 DDL 在各节点执行时携带一致的设置上下文; - 新增
distributed_ddl_output_mode设置,支持四种模式:none、throw(默认)、null_status_on_timeout、never_throw,让分布式 DDL 的超时/失败处理更可控; - 同时修复与增强
Replicated数据库引擎(该 PR 还包含多项杂项修复)。
4. 窗口函数:RANGE OFFSET 帧与 lagInFrame/leadInFrame(PR #21895)
RANGE OFFSET帧支持浮点类型;- 新增窗口函数
lagInFrame/leadInFrame,语义与lag/lead类似,但尊重窗口帧边界(lag/lead在整表范围上计算,忽略帧)。当帧为between unbounded preceding and unbounded following时两者结果一致(关闭 issue #5485)。
5. windowFunnel 新增 strict_increase 选项(PR #22025)
windowFunnel函数新增选项strict_increase,保证漏斗中的每个事件只被计算一次(解决 issue #21835),避免同一事件重复命中多个漏斗层级。
6. system.errors 表增强(PR #21529 / #22058)
- PR #21529:
system.errors新增last_error_time、last_error_message、last_error_stacktrace、remote四列; - PR #22058:
system.errors.stack_trace类型从String改为Array(UInt64),降低错误采集开销。
7. clickhouse-client 交互增强(PR #22105)
clickhouse-client 新增不区分大小写的历史搜索/导航以及**子词移动(subword movement)**能力,长命令行的编辑体验明显改善。
8. system.processes 新增 current_database 列(PR #22365)
system.processes表新增current_database列,展示查询执行时的当前数据库,便于多库场景下的会话审计。
9. PostgreSQL 生态增强(PR #21710 / #21711 / #21839)
- PR #21710:PostgreSQL 字典源支持副本优先级(replica priority);
- PR #21711:PostgreSQL 存储引擎/表函数支持非默认 schema的表(关闭 issue #21701);
- PR #21839:为 PostgreSQL 表/数据库引擎及字典源增加连接池(修复 issue #21444)。
10. S3 磁盘能力演进(PR #21837 / #22070)
- PR #21837:修复使用缓存盘时"目标目录非空导致无法移动目录"的 Bug(DiskS3 仍属开发中的实验特性);
- PR #22070:支持将既有 S3 磁盘迁移到具备备份恢复(backup-restore)能力的 schema。
11. 其他值得关注的改进
- MaterializeMySQL:为
_version列增加 minmax 跳过索引(PR #20382);连接断开时尝试重连 MySQL(PR #20961)。 - 空 part 抑制:
optimize_on_insert开启时,INSERT 不再创建空 part(PR #20387,修复 issue #20304)。 - CROSS JOIN 重写增强:支持更多
CROSS JOIN改写为INNER JOIN的 case(PR #20392)。 - Map 类型整数键:改进
Map数据类型的整数键支持(PR #21157);修复arrayElement与Map、常量整数参数组合的 Bug(PR #21699)。 - Graphite rollup 配置校验:age 与 precision 必须随 retention 单调递增,否则抛异常(PR #21496)。
- system.parts 增强:分区键不含
Date/DateTime但含且仅含一个DateTime64列时,在system.parts/system.parts_columns的min_time/max_time列中暴露其取值,并为system.parts_columns补齐min_time/max_time列(PR #22011)。 - 窗口函数相关修复:修复窗口函数与"按主键顺序读取"优化组合时的错误
ORDER BY结果(PR #21915)。 - Web UI:
Array与Map类型在 Web UI 中格式化更友好(PR #21798)。 - EmbeddedRocksDB:在系统表中展示数据目录路径(PR #21903)。
- 元组 NULL 比较:
(NULL, NULL) IN ((0,0),(3,1))返回 0 而非类型不兼容异常(PR #22063)。 - TinyLog/Log 引擎:修复跨线程 rwlock 解锁导致的未定义行为(PR #22560 / #22583)。
- simdjson 升级:更新到 0.9.1(PR #22057)。
六、Bug 修复(Bug Fix)重点解读
21.4 的 Bug 修复数量庞大,按主题归并如下(含后续回迁的补丁):
1. 复制与 MergeTree 一致性
- 修复
ReplicatedMergeTree上并发OPTIMIZE与DROP(PR #21716); - 修复
ReplicatedMergeTree的ALTER MODIFY COLUMN在 Decimal 位宽不变时无法修改类型(PR #21728); - 修复
ReplicatedMergeTree的OPTIMIZE/ALTER等待逻辑——表被 detach 或重启时查询不再挂起(PR #22118); - 修复非复制 MergeTree 上
MOVE PARTITION TO TABLE目标表已有同名 part 时的行为(PR #21760); - 修复
force_drop_table对MATERIALIZED VIEW不生效(PR #20626,修复 issue #18943); - 修复
CollapsingMergeTree合并可能产生index_granularity + 1行 granule、进而触发Incomplete granules are not allowed报错并阻塞合并的问题(PR #21976); - 修复
tmp_fetch_XXX already exists错误:fetch part 失败后遗留的临时目录会被清理(PR #22411,修复 issue #14197)。
2. 优化器正确性(重点关注升级后行为变化)
- 修复
optimize_skip_unused_shards开启且 WHERE 为常量时可能跳过全部分片返回错误空结果(PR #21550); - 修复
optimize_skip_unused_shards开启且零分片被使用时的Cannot find column错误(PR #21579); - 新增
optimize_skip_unused_shards_limit设置(PR #21512),限制optimize_skip_unused_shards评估的分片键取值数量; - 修复 WHERE/HAVING 被下推到 GROUP BY 之前导致的错误结果甚至崩溃(PR #21841,修复 issue #21773);
- 修复
SELECT含常量 WHERE 且源表列名为数字时的异常(PR #22270); - 修复标量子查询索引分析(PR #21766,修复 issue #21717)。
3. 网络与分布式查询
- 修复
async_socket_for_remote=1时分布式请求取消失效(PR #21643); - 修复 hedged connections 重叠导致的
Unknown packet 9 from server(PR #21941),以及use_hedged_requests=0+async_socket_for_remote=1下的查询取消问题(PR #22183); - 为有缺陷的 Linux 内核自动禁用
async_socket_for_remote/use_hedged_requests(PR #22109); - 修复 secure socket 的收发超时与非阻塞读(PR #21429)、Poco SecureSocket 内 SSL 对象的竞态(PR #21456);
- 修复
clusterAllReplicas表函数返回错误_shard_num(PR #21498,关闭 issue #21481); - 修复
InterserverIOHTTPHandler未捕获异常(PR #22146)。
4. S3 与磁盘
- 修复 S3 表在配置更新后仍持有旧凭证(PR #21457);
- 修复写 S3 出错时调用
std::terminate(PR #21624); - 回退 S3 连接池(PR #21737);
- 改进
WriteBufferFromS3的错误处理与日志(PR #21836); - 修复 S3 零拷贝复制在混合存储下的 Bug(PR #22378)。
5. 安全与加密
decrypt函数在 AEAD 模式下缺少对密文最小长度的校验,已修复(PR #22064,关闭 issue #21897);- 修复
remote_url_allow_hosts存在配置节但无条目时的"开放远程主机过滤"问题(PR #20058)。
6. 外部数据源与字典
- 修复 Avro 格式在 Kafka 中的解析(PR #21640 关联、PR #21438,修复 issue #21437);
- 修复 ip_trie 字典
access_to_key_from_attributes下访问不存在属性时的 SIGSEGV(PR #21692); - 修复
ClickHouseDictionarySource配置循环(PR #22479,关闭 issue #14314); - 修复
StorageJoin缺类型转换导致的 SIGSEGV(PR #21646)。
7. 格式与内存安全
- 修复
tokenbf_v1全文索引的越界读(PR #22421,关闭 issue #19233,回迁于 #22532); - 并行解析例程补上内存记账,防止超大结果块时的 OOM(PR #22425,关闭 issue #22008);
- 修复 TSV 末尾无换行的空字符串反序列化(PR #22527,关闭 issue #20244;临时规避:设置
input_format_null_as_default=0); - 修复
PODArray元素大小既非 16 的约数也非倍数时可能出现的缓冲区溢出(PR #21533)。
8. 其他典型修复
- 修复窗口函数读取顺序优化组合时的
ORDER BY错误(PR #21915); - 修复首个 CatBoost 模型执行死锁(PR #21844,关闭 issue #13832);
- 修复聚合函数
Distinct组合子在两级聚合下的崩溃(PR #21818); - 修复 HTTP
multipart/form-dataPOST 读取(PR #21936); - 修复
Log引擎嵌套类型无列 SELECT 时的LOGICAL_ERROR(PR #22654); - Docker entrypoint:
LOG_PATH为空时避免对.执行 chown(PR #22102),http_port不在配置时不再报错(PR #22132); - 修复客户端在服务端写块异常时得到误导性
Data compressed with different methods消息(PR #22427)。
七、构建、测试与打包改进(Build/Testing/Packaging)
21.4 在工程侧最重要的变化是ppc64le 架构支持的大规模完善:修复编译、指令指针寄存器、配置与 cctz 时区嵌入、jemalloc、Fedora/RHEL/CentOS 的 libclang_rt.builtins 查找、CMake 变量、boost 编译,并支持用 Clang 在 ppc64le 上编译(PR #22430、#22445、#22447、#22458、#22469、#22474、#22476),同时重新启用了 aarch64 上的 S3/AWS 库(PR #22484)。
其他要点:
- macOS:修复共享库构建(PR #20184)与原生 Xcode/AppleClang 的 ALL_BUILD 构建(PR #22289)。
- 工具链:CMake 脚本支持查找 llvm-12 二进制;适配 CMake 3.19;clang 的
-fuse-ld改为--ld-path(PR #21597)。 - Docker:clickhouse-server 镜像 Dockerfile 引入
deb_location与single_binary_location两个构建参数(PR #21977),并新增后缀参数(PR #22301);容器加入tzdata(读取 ORC 格式必需,关闭 issue #14156)。 - 测试:新增 ALL/NONE 权限测试、ROW POLICY 测试并清理既有测试(PR #21354);为 NuKeeper(即 Keeper)引入 Jepsen 一致性测试(PR #21677);SQLancer CI 启用状态检查(PR #22015);RBAC testflows 增加内存信息检查(PR #22403)。
- 静态检查:允许在 release 构建中使用 clang-tidy(自动启用断言,PR #21914)。
八、其他与 datasketches 支持(Other / 专项新特性)
- 分布式 hedged requests 相关测试更新(PR #21998);避免在
ReadBufferFromPocoSocket/WriteBufferFromPocoSocket的 nextImpl 中重复设置相同超时导致竞态(PR #22343)。 - 文档与杂项收尾:若干文档翻译改进、GUI 工具列表更新(新增 SeekTable)、依赖扁平化等(NO CL ENTRY 条目,PR #21729 / #21768 / #22078 / #22374)。
- 专项新特性:datasketches 支持(issue #14893):21.4 开始引入ThetaSketch,用于集合运算(PR #22207)。ThetaSketch 是近似基数/集合操作库,支持多集合的并集、交集、差集估算,为超大规模去重与集合分析提供亚线性内存方案。
九、升级与使用建议总结
- 升级前复核分片键:若使用
cutToFirstSignificantSubdomainCustom且自定义顶级域名列表包含 3 级以上域名,检查是否影响分片路由。 - 关注 toStartOfInterval 语义:小时间隔现在从午夜对齐,报表/分组 SQL 的区间边界可能变化。
- 适配 system.dictionaries 列名:依赖
keys列的监控或查询需改为key.names/key.types。 - 善用新能力:IP 网段判定用
isIPAddressInRange;时区诊断用timezoneOf;分区裁剪优先用_partition_id;S3 存储上的复制表可评估零拷贝复制收益。 - 理性对待性能设置:
NONE编码与 mmap IO(min_bytes_to_use_mmap_io)均有明确适用边界与生产环境风险,按官方建议谨慎使用。
本文所有源码路径均可在当前仓库中直接查阅,例如 toStartOfInterval.cpp、isIPAddressInRange.cpp、timezoneOf.cpp、cutToFirstSignificantSubdomainCustom.cpp、ExecutablePoolDictionarySource.cpp 以及 StorageSystemClusters.cpp,感兴趣的读者可以沿着这些入口继续深入 21.4 版本的实现细节。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考