ClickHouse v23.10.1.1976-stable 版本解析:S3Queue 全面重写、新 SQL 函数与倒排索引优化
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
本文基于 ClickHouse 官方变更日志 docs/changelogs/archive/v23.10.1.1976-stable.md 展开,逐条解读 v23.10.1.1976-stable 版本(commit13adae0e42f,对比基线为 v23.9.1.1854-stable,commit8f9a227de1f)的全部变更:哪些行为发生了不兼容变化、新增了哪些函数与 SQL 能力、性能优化集中在哪些路径,以及升级前必须处理的配置项。读完本文,你可以在升级该版本时准确评估风险点,并能结合源码路径验证每项功能的实现位置。
一、版本定位与变更结构
该版本是 2023 年 10 月发布的稳定版,变更日志按官方惯例分为六个区块:
| 区块 | 含义 | 升级关注度 |
|---|---|---|
| Backward Incompatible Change | 不兼容变更,可能直接改变既有行为 | 高,升级前必读 |
| New Feature | 新函数、新语法、新存储能力 | 中,按需采用 |
| Performance Improvement | 性能优化 | 中 |
| Improvement | 行为改进与增强 | 中低 |
| Build/Testing/Packaging Improvement | 构建与打包改进 | 低(自构建者关注) |
| Bug Fix | 官方 stable 版本可见缺陷修复 | 按问题域关注 |
下面按区块逐条解析,并在可溯源处给出当前仓库中的源码位置。
二、不兼容变更:升级前必须了解的 7 个行为变化
2.1 S3Queue 引擎完全重写
这是本版本最大的架构级变更。S3Queue 存储引擎被整体重写:
- 改变了 ZooKeeper 中的状态保存方式:减少 ZooKeeper 请求量,并在"确定状态不会变化"的场景下缓存 ZooKeeper 状态;
- S3 轮询策略调整:轮询 S3 的频率降低,行为更温和;
- TTL 与最大条数限制的维护方式变化:被追踪文件的 TTL / max 限制现在由后台进程维护;
- 新增系统表:
system.s3queue与system.s3queue_log,用于观察队列状态。
对应 PR 为 #54422,解决了 issue #54998。从源码结构看,S3Queue 相关实现位于src/Storages目录下的 S3Queue 模块,升级后可通过新增的两张系统表验证队列运行状态。
2.2 不再自动删除损坏数据分片
此前 ClickHouse 存在一个"自动移除 broken data parts"的选项,本版本起该选项被移除(PR #55184,issue #55174)。这意味着损坏分片不再被静默清理,需要用户显式处理。
与此相关的两个配套变化值得注意:
- 内存型数据分片(in-memory parts)不再能从前写日志(WAL)中恢复。如果此前配置过 in-memory parts,升级前必须先将其移除(PR #55186);
- 后续补丁(#55557)保证用户引用已删除的 MergeTree 设置时不会落入
UNKNOWN_SETTING错误,而是给出友好提示——这是对删除损坏分片相关设置后的兼容性补救。
2.3 移除 Meilisearch 集成
Meilisearch 集成被移除(PR #55189)。原因是它仅与旧版 0.18 兼容,而 Meilisearch 新版本改变了协议导致无法工作。官方同时表示欢迎社区协助将其修复后重新引入。如果你的应用依赖该集成,升级前需要改用其他全文检索方案。
2.4 directory monitor 更名为 background INSERT
"目录监控"概念被正式更名为background INSERT,所有*directory_monitor*前缀设置全部改名为distributed_background_insert*。官方明确说明向后兼容得到保留:旧设置名作为别名仍然有效(PR #55978)。建议在配置中尽早迁移到新名称。
2.5 区分 send_timeout 与 receive_timeout
网络超时处理中,send_timeout与receive_timeout被明确区分开(PR #56035),此前两者会被混用。对依赖超时行为调优的部署(例如慢查询、大结果集拉取)可能观察到超时触发时机的差异。
2.6 不同单位的 TimeInterval 比较将抛异常
对单位不同的时间区间(例如IntervalYear与IntervalDay)做比较时,本版本起将抛出异常(PR #56090,issue #55942)。此前行为是比较底层的数值而忽略单位——如果你的业务代码恰好依赖了这一旧行为,升级后需要显式转换为同一单位再比较。
三、新特性:函数、语法与存储能力
3.1 新增标量函数
arrayFold:对多个等长数组做归约。函数形式为arrayFold(accum -> expression, accum_init, array1, ..., arrayn),对 n 个基数相同的数组应用 lambda 函数并将结果累积到累加器中(PR #49794)。注意:合并后参数顺序经过调整("arrayFold: Switch accumulator and array arguments",PR #55948),累加器与数组参数的相对位置以最终版本为准。实现位于 arrayFold.cpp。
arrayRandomSample(arr, k):随机采样。从输入数组中返回 k 个元素的随机样本(PR #54391)。此前只能通过arrayReduce('groupArraySample(3)', ...)之类的较繁琐语法实现。
jsonMergePatch:JSON 字符串合并。处理 JSON 对象字符串时,可将多个 JSON 对象字符串按 RFC 7386(JSON Merge Patch)语义合并为一个(PR #54364,后续补丁 #56020 修正了实现细节)。实现位于 jsonMergePatch.cpp。
byteSwap:无符号整数字节序反转。特别是用于内部以无符号整数表示的类型(如 IPv4)的字节反转场景(PR #55211,后续 #55607 补充了 16/32 字节整数支持)。实现位于 byteSwap.cpp。
formatQuery()/formatQuerySingleLine():SQL 字符串格式化。前者返回可能跨多行的格式化查询,后者返回不含换行的单行版本(PR #55239)。两者都可用于在查询中动态生成、美化 SQL 文本。
getHttpHeader:获取 HTTP 请求头。返回发起请求到 ClickHouse 服务器时所用 HTTP 请求头的值;非 HTTP 协议请求或不存在的头返回空字符串(PR #54813)。需要留意:变更日志的 "NO CL ENTRY" 区块记录了该 PR 曾一度被 revert(#56109),说明该功能的最终可用性以实际版本二进制中的函数注册表为准,升级后可直接SELECT getHttpHeader('Host')验证。
3.2 新增聚合函数与组合器
lttb聚合函数:LTTB 降采样。使用 Largest-Triangle-Three-Buckets 算法对数据降采样,专为图表可视化场景设计(PR #53145)。实现位于 AggregateFunctionLargestTriangleThreeBuckets.cpp。典型用法如:
SELECT lttb(100)(x, y) FROM measurements-ArgMin/-ArgMax聚合组合器。允许"只按最小值/最大值聚合"(PR #54947),并借此将组合器实现整理到独立目录。典型用例是求某指标在组内取极值时的关联字段,同时避免argMin(arg, val)中额外排序开销。
3.3 新增 SQL 语法与语句
SHOW SETTING setting_name(PR #55979):SHOW SETTINGS的简化版,查看单个设置项的当前值、默认值与描述;CHECK TABLE ... PART 'part_name'(PR #53404):CHECK TABLE性能与可用性改进——支持发送进度更新、支持取消,并可对指定 part 执行校验;SHOW MERGES(PR #55815,后续 #56124 美化输出):查看正在进行的 merge 过程;RENAME db.t1 TO db.t2省略TABLE关键字(PR #55373);- 分区 DDL 支持查询参数:
ALTER TABLE t DROP PARTITION等语句可使用{name:Type}参数(PR #49516,... ACTION PARTITION的参数支持由 #55604 补齐); SYSTEM DROP SCHEMA FORMAT CACHE [FOR Protobuf](PR #55064):可手动丢弃 Protobuf 等格式的 schema 缓存;DESCRIBE行为增强:新增describe_include_virtual_columns(结果中包含虚拟列)与describe_compact_output(仅返回列名和类型,PR #55129)。
3.4 输入/输出格式扩展
- DWARF 输入格式(PR #55450):从 ELF 可执行文件/库/目标文件读取调试符号,典型用途是把 coredump 的符号信息灌入表中做分析;
- Npy 格式(PR #55982):支持读取 NumPy 数组文件,例如:
SELECT * FROM file('example_array.npy', Npy)3.5 日志引擎的错误处理模式
RabbitMQ、NATS 与 FileLog 引擎支持保留解析失败记录(PR #55477,issue #36035),语义与kafka_handle_error_mode对齐:
| 引擎 | 设置项 | 出错时填充的虚拟列 |
|---|---|---|
| NATS | nats_handle_error_mode | _error、_raw_message |
| RabbitMQ | rabbitmq_handle_error_mode | _error、_raw_message |
| FileLog | handle_error_mode | _error、_raw_record |
取值为default时解析失败抛异常;取值为stream时错误与原始记录写入虚拟列,不中断消费。
3.6 存储引擎与索引
空间填充曲线键的条件下推。若表按空间填充曲线排序(例如ORDER BY mortonEncode(x, y)),则对参数列的范围条件(如x >= 10 AND x <= 20 AND y >= 20 AND y <= 30)可以被用于索引分析(PR #55642,issue #41195 及更早一系列 issue 的延续)。开关设置analyze_index_with_space_filling_curves可启用或禁用该分析,已在 Settings.cpp 中注册。
倒排索引的max_rows_per_postings_list。倒排索引不再保存"匹配行过多"的 token,以节省空间并避免低效的索引查找(PR #55616)。旧定义中的density参数(控制何时不保存 token)被移除,替换为更直观的max_rows_per_postings_list(默认 64k),直接限制 posting list 中允许的最大行号数量。该设置同样在 Settings.cpp 中定义。
其他存储侧新能力:
optimize_trivial_approximate_count_query:为 EmbeddedRocksDB 存储启用count()近似,并为 StorageJoin 启用 trivial count(PR #55806);force_optimize_projection_name:传入投影名后,ClickHouse 会强制校验该投影在查询中至少被使用一次(PR #56134,issue #55331);create_table_empty_primary_key_by_default:默认ORDER BY ()的控制开关(PR #55899);materialized_postgresql_use_unique_replication_consumer_identifier:允许多个 MaterializedPostgreSQL 表跟随同一张 Postgres 表,默认关闭以保持兼容(PR #55145,issue #54918);- 外部 HTTP Basic 认证器(PR #55199):支持将认证委托给外部 HTTP 服务;
- Replicated 数据库引擎引入 replica groups(PR #54421,issue #53620)。
3.7 Keeper 客户端
新增两条命令(分别由 PR #55485 与 #55898 引入):
get_all_children_number:返回某路径下所有后代节点的数量(含间接子节点);get_direct_children_number:返回某路径下直接子节点的数量。
两者配合system.zookeeper可低成本估算子树规模,避免拉取完整节点列表。
四、性能改进
本版本性能条目数量较多,按主题归纳如下:
查询执行与并发
query_plan_preserve_num_streams_after_window_functions(PR #50771):窗口函数求值后保留流数量,使并行流处理可以延续到窗口函数之后;- 小数据量时释放更多 num_streams(PR #53867);
- 修复 Context 锁竞争:对大量短并发查询的性能有显著提升(PR #55121);
ColumnVector::insertMany/insertManyFrom优化(PR #55714);IN函数中 set 元素类型与列类型不完全一致时的 cast 函数执行期缓存(PR #55712)。
索引
- 倒排索引创建性能提升 30%:
std::unordered_map替换为absl::flat_hash_map(PR #55210); - 倒排索引 posting list 在序列化前优化为最小表示,按数据重复度可显著降低索引空间占用(PR #55069);
- 为二级索引的 marks 缓存设置合理的默认大小,避免反复加载 marks(PR #55654);
- 读取 skip 索引时避免不必要的 index granule 重建(PR #55683,issue #55653)。
外部聚合与 Map 类型
- 产生大量临时文件时外部聚合的性能(PR #55489)与内存占用优化(PR #54798);
- Map 取值的键位置预测优化:实践中同一 Map 列内键结构通常一致,可预测下一行键位置以减少比较(PR #55929)。
数据源
- ORC 下推过滤(rowgroup 级别,PR #55330);
- Parquet 结构体字段裁剪在部分场景下不生效的问题修复(PR #56117);
- RoaringBitmap 序列化前优化(PR #55044)。
五、其他改进(Improvement)
除性能条外,Improvement 区块包含大量行为增强,择要说明:
兼容性与生态
- Kusto 查询语言方言支持的第二阶段(PR #42510,第一阶段为 #37961);
- 多项 MySQL 兼容增强:
information_schema.tables新增table_rows、information_schema.columns新增extra字段(PR #55215);toDayOfWeek()/toYearWeek()/toWeek()支持 String 参数(PR #55589);(add|subtract)(Year|Quarter|...)系列函数支持字符串日期参数(PR #55869);(add|sub)Date()与加/减运算符支持字符串日期 + INTERVAL(PR #55960)。官方明确说明这些改动是为了 MySQL 兼容性,并且是 Tableau Online 集成的需要; untuple()对命名字段元组的结果列名生成规则变化:有别名时列名由 untuple 别名与元组元素别名组合(PR #55123)。
可靠性与易用性
async_socket_for_remote模式下分布式查询现在遵守max_threads限制(PR #53504):此前部分查询可能创建多达max_distributed_connections数量的线程,拖垮服务器性能——这是集群环境下容易被忽视的隐患,升级可获得直接收益;- 分区内 part 数量超过 1000 时的整体韧性增强,可能减少
TOO_MANY_PARTS错误(PR #55526); - ReplicatedMergeTree 启动时检查意外 part(本地存在但 ZooKeeper 中没有):意外 part 移入 detached 目录并尝试恢复祖先 part,本版本改为优先恢复最近的祖先而非随机 covered part(PR #55645);
- 损坏 part 在服务器关闭前打印其磁盘路径(PR #56181):此前 part 损坏导致服务器无法启动时几乎无从定位是哪个 part;
date_time_overflow_behavior设置(PR #55696):取值ignore/throw/saturate,控制 Date/Date32/DateTime64/整型/浮点向日期时间类型转换的溢出行为;apply_deleted_mask关闭后可读取被轻量级 DELETE 标记删除的行,便于调试(PR #55952);- 日志中更完善地隐藏机密信息(PR #55089);
system.parts_columns新增substreams与filenames字段(PR #55108);system.clusters新增internal_replication字段(PR #55377)。
协议与接口
http_write_exception_in_output_format场景下异常输出使用声明的查询格式(PR #55739),并修复了该设置下错误查询结果的问题(PR #56135);use_mysql_types_in_show_columns仅影响SHOW COLUMNS(PR #55481),并新增mysql_map_string_to_text_in_show_columns、mysql_map_fixed_string_to_text_in_show_columns控制String/FixedString输出为TEXT还是BLOB(PR #55617);- 异步插入支持原生协议的外部数据(此前仅限内联数据,PR #54730);
- 查询参数在自定义 HTTP handler 下可用(PR #55521);
clickhouse-keeper支持使用内嵌配置运行(PR #56086);clickhouse-local中删除当前数据库后仍可执行部分查询并切换数据库,行为与clickhouse-client一致(PR #55853);- 所有字典支持
dictionary_use_async_executor设置(PR #55839); - RocksDB 写入性能改进(PR #55732);
- Kusto 实现中的竞态条件修复(PR #55615)。
其他值得注意的行为修正
- 直接字典配置 lifetime 字段时在建表期即被拒绝(PR #49043,issue #27861);
zookeeper_connection重构并新增xid列(PR #50702);OPTIMIZE配合optimize_throw_if_noop=1时,不同 part 投影不同导致的 "unknown reason" 报错被修复(PR #55130);- 投影分析现在仅基于查询计划顶层进行,
query_plan_optimize_projection设置随之废弃(PR #55112); - 按行估计动态调整并行副本数量(PR #51692);
- 数学减号
−字符(Unicode 减号)在查询中可用(PR #54100); - CSV 格式允许未加引号字符串中包含 CR(PR #56046,issue #39930);
minSampleSizeContinous拼写错误修正为minSampleSizeContinuous,旧名保留兼容(PR #56143)。
六、构建 / 测试 / 打包改进
对自构建与 CI 用户而言,本版本包含:
- AVX 构建修复(PR #55049):此前启用
-DENABLE_AVX=ON -DENABLE_AVX2=ON -DENABLE_AVX2_FOR_SPEC_OP=ON构建时,snappy 会因未启用SNAPPY_HAVE_X86_CRC32而报unknown type name '__m256i'编译错误; - Docker 初始化逻辑:数据库已初始化则跳过重复初始化,可修复超大库/多节点环境下 1000 次加载失败后容器无限重启的问题(PR #50724);
- Darwin 专用构建任务:产出包含子模块源码的资源包,可免 checkout 子模块构建(PR #51435);
- 包完整性:为 tgz 校验 sha512,TGZ.sha512 文件只写文件名;keeper 使用独立仓库(PR #55717);
- 从 clickhouse-server 包中独立启动 clickhouse-keeper 的问题解决(PR #55226);
- 测试侧:RabbitMQ 升级至 3.12.6 并改进日志收集(PR #55424)、集成测试新增
instance_env_variables选项(PR #55208)、s390x 平台的 HDFS 支持(PR #56128)、jbod balancer 测试去抖动(PR #56175)。
七、缺陷修复(Bug Fix)
该区块修复了 50+ 个用户可见缺陷,按问题域归纳(括号内为 PR 号):
MergeTree / 副本 / Part 管理
- mutation 中跳过倒排索引文件的硬链接(#47663);
- adaptive granularity 下
ALTER UPDATE的 skip 索引重算修复(#55202); - S3 上非 zero-copy 的 ReplicatedMergeTree 无法 drop detached partition 的修复(#55309);
- SummingMergeTree 的
SELECT FINAL中 Nested 列错误合并修复(#55276); - 轻量级删除 part 的
storage.has_lightweight_delete_parts标记在 part 加载时正确设置; DROP_RANGE与已有 block 提交之间的竞态修复;- least_used JBOD 策略的空闲空间统计错误修复(#56030)。
查询执行与崩溃
MergeSortingPartialResultTransform中因remerge()后零块导致的 SIGSEGV(#55335);CreatingSetsTransform在错误路径上的数据竞争(#55338,v2 修复 #55786);- 稀疏列上的函数执行(#55275)与窗口函数(#55895)修复;
- 虚拟列 OR 过滤条件查询的过滤逻辑修复(#55418,重提版 #55678);
- 表函数内子查询求值时标量缺失问题(#56057);
- Buffer 表并发 ALTER 与 INSERT 导致 "Block structure mismatch"(#55995,最终修复 #56140);
QueryNormalizer循环别名崩溃修复(#55602);- 窗口函数、
show databases limit等多项修正。
外部系统与格式
- Iceberg 存储的文件获取与一系列修复改进(#55144、#55695);
- MongoDB 连接问题(#55419)、ODBC 与 MS SQL Server 交互 "Invalid cursor state"(#55558)、MySQL 接口布尔表示(#55427)与文本协议 DateTime 格式化(#55479);
- AvroConfluent 从 schema registry 拉取 schema 的修复(#55991);
- Native/ORC 输入格式可能的段错误(#55891);Arrow 字典列输入输出修复(#55989);
dateTime64ToSnowflake64()非默认 scale 修复(#55983);- 精确浮点解析开启时非法字符串转浮点抛异常(#55861);
- CTE 含状态函数时禁用谓词下推(#55871);
- 压缩器在 buffer 未 finalize 时的潜在内存泄漏(#55262);
- StorageHDFS 内存泄漏(#55370);
- LDAP 授权角色更新死锁(#55119)与备份死锁(#55132);
accurateCastOrNull()修复重新合入(#54629);- 无
AS创建的 Distributed 表 DEFAULT 检测修复(#55060)。
八、NO CL ENTRY 与 NOT FOR CHANGELOG 区块说明
变更日志末尾两个区块记录了不对外承诺行为的内部提交,阅读时应注意:
- NO CL ENTRY区块包含 10 条记录,多为Revert 操作:例如 Revert "Support SAMPLE BY for VIEW"(#55357)、Revert "Add function getHttpHeader"(#56109)、Revert "Fix output/input of Arrow dictionary column"(#56150),以及 dashboard 单图表按钮、pdqsort 排序优化等回滚。这说明这些特性在本版本内不稳定或被撤回,使用相关能力前应在目标版本上实测验证;
- NOT FOR CHANGELOG / INSIGNIFICANT区块(约 90 条)主要是测试修复、CI 调整、Analyzer/Planner 内部重构、依赖版本提升(croaring 2.0.x、curl 8.4、gRPC 多次升级、protobuf 升级)等内部提交,不影响用户行为。
九、升级建议与仓库内验证路径
结合本文解析,升级到 v23.10.1.1976-stable 前建议按顺序检查:
- S3Queue 用户:确认 ZooKeeper 中队列元数据的兼容性与
system.s3queue、system.s3queue_log可用性,这是最大的行为变化; - 使用过 in-memory parts 的部署:升级前移除相关 part 配置(WAL 不再能恢复内存 part);
- 依赖自动清理损坏 part 的运维流程:改为显式处理 broken part,并利用新能力——关闭前打印损坏 part 路径(Improvement #56181)定位问题;
- 配置迁移:
*directory_monitor*→distributed_background_insert*(旧名仍作别名保留); - 依赖旧行为的 SQL:不同单位 TimeInterval 比较、按底层数值比较的场景需改写;
- 验证新能力:
lttb、arrayFold、arrayRandomSample、jsonMergePatch、byteSwap、SHOW SETTING、SHOW MERGES、DWARF/Npy 格式等均可通过直接执行 SQL 验证,实现文件分别位于 src/Functions 与 src/AggregateFunctions 目录,设置项定义可查 src/Core/Settings.cpp; - 集群并发短查询场景:Context 锁竞争修复(#55121)与
max_threads限流修复(#53504)升级后可观察 QPS 与延迟指标的改善。
变更日志原文(含全部 PR 编号与贡献者署名)见 v23.10.1.1976-stable 变更日志,同目录下的其他归档版本日志可用于做跨版本对比。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考