向后不兼容的变更
查询、函数和语法变更
- 对于定义体为针对单个
Distributed表的简单SELECT的视图,现在会将整个外层查询下推到各分片执行 (新增设置optimize_trivial_view_pushdown_to_distributed,默认启用) 。这会改变此类视图的可观察行为:在视图引用上指定的FINAL和SAMPLE现在会传递给分片本地表,而不再被忽略;此外,在单分片集群上不再报告extremes。如需恢复之前的行为,请设置optimize_trivial_view_pushdown_to_distributed = 0。#101791 (simonmichal)。 - 轻量级
UPDATE的补丁分区片段现在采用新的 v2 磁盘格式,按 (sorting_key..., _block_number, _block_offset) 排序,并通过新的合并算法应用。峰值内存取决于排序键相同的最大连续段,而不再取决于整个补丁;跨越合并边界的更新也不再回退为在内存中通过 Join 应用。旧格式的补丁分区片段仍可读取。从 26.8 之前的版本滚动升级时,请保持patch_parts_version = 'v1'或使用compatibility设置,直到所有副本均完成升级。#103182 (CurtizJ)。 AggregatingMergeTree现在会在建表时拒绝以下 schema:其中存在既不属于排序键、也不是聚合状态度量列 (AggregateFunction/SimpleAggregateFunction) 的列。此类列在后台合并时会被静默折叠为任意值,导致基于这些列进行GROUP BY或过滤的查询返回错误结果。如需恢复之前的行为,请设置allow_dimensions_outside_sorting_key = 1。#108087 (alexey-milovidov)。- ClickHouse 现在对同步和异步插入一律使用统一的插入去重哈希,旧版的逐次插入去重行为已移除。服务器设置
insert_deduplication_version作为迁移保护予以保留:若将其设为旧版值 (old_separate_hashes或compatible_double_hashes) ,服务器将拒绝启动。如需从使用旧版值的版本升级,请先运行支持compatible_double_hashes的版本 (该模式会同时写入旧版哈希和统一哈希) 。对于复制表,运行时长至少应为replicated_deduplication_window_seconds(默认为一小时;默认窗口会保留该时间段内所有插入的统一哈希,通常足以覆盖插入重试循环) 。对于non_replicated_deduplication_window> 0 的非复制表,该窗口基于插入次数而非时间,因此compatible_double_hashes模式下至少需要完成相应次数的插入。之后,在升级到此版本之前,请移除该设置 (或将其设为new_unified_hash) 。#108361 (CheSema)。 - 设置
use_legacy_to_time现在默认为0,因此toTime会将值转换为Time数据类型,而不再将日期时间转换为固定日期。如需沿用旧版行为,可使用toTimeWithFixedDate函数,或设置use_legacy_to_time = 1。#108729 (alexey-milovidov)。 - 朴素贝叶斯模型 (供
naiveBayesClassifier使用) 现在配置为采用NAIVE_BAYES布局的字典,在加载时基于一张按类别预聚合的 n-gram 计数表构建,取代此前的服务器端配置方式 (即引用序列化.bin模型文件的 XML config 文件) 。旧方式已不再受支持——现有模型必须重新创建为字典。同时新增三个与naiveBayesClassifier配套的函数:naiveBayesClassifierWithProb返回预测类别及其概率,naiveBayesClassifierWithAllProbs返回所有类别及各自的概率,naiveBayesNgrams则以与字典相同的方式将文本切分为 n-gram,用于从原始带标签文本构建训练数据。此外还进行了多项性能优化:在一个 9.7 MiB 的码点三元组语言模型上,内存占用降低约 49 倍 (从 1.84 GiB 降至 38 MiB) ,加载速度和分类速度均提升约 11 倍。#108773 (nihalzp)。 max_insert_threads设置的默认值已从1(不并行) 改为auto,即取服务器可用的 CPU 核心数 (内存紧张时会依据max_insert_threads_min_free_memory_per_thread相应减少) 。这样一来,INSERT SELECT默认即并行执行;对于符合条件的普通INSERT,只要目标写入路径能够安全地扇出,其写入端同样可以并行化。此变更可能会影响所创建的数据分区片段数量以及插入行的顺序。如需恢复先前的行为,请将max_insert_threads设为1,或将compatibility设为低于26.8的版本。#109000 (alexey-milovidov)。#109006 (alexey-milovidov)。- 读取 CSV 中的 bare
Tuple时,现在无论处于哪个位置,每个元素都对应一个字段,因此顶层元素字段中的\N仅表示该元素本身,并会对其应用input_format_null_as_default。此前,开头的\N会被视为整列为 null,导致该行被替换为列默认值,随后其余元素单元格解析失败。对于为整个 bareTuple只提供单个字段的行,这是一项向后不兼容的变更:此类行现在会因缺少其余元素而被拒绝;而对于单元素Tuple,由于两种方式下字段数相同,会静默返回元素默认值,而非列的DEFAULT。设置input_format_csv_deserialize_separate_columns_into_tuple = 0即可恢复将此类字段作为整列读取。#109744 (groeneai)。 - 为
CREATE USER和ALTER USER新增VALID FOR <interval>子句,作为VALID UNTIL的简写形式。过期时间在查询执行时按当前时间加上指定时间间隔计算,并以VALID UNTIL形式存储。system.users表的valid_until列类型由Array(DateTime)改为Array(DateTime64(0)),以便精确表示 2106 年之后的过期时间;读取该列的工具需适配新类型。#110171 (alexey-milovidov)。 EXPLAIN SYNTAX现在将格式化后的查询作为单条String记录 (内含换行符) 返回,而不再每行一条记录,因此其输出为可直接使用的单行结果 (例如,SELECT count() FROM (EXPLAIN SYNTAX ...)返回1) 。该行为由新增的single_record选项控制,默认值为1;设置single_record = 0可恢复以往每行一条记录的输出。其他EXPLAIN类型 (PLAN/PIPELINE/AST) 仍保持逐行的树形输出。#110479 (alexey-milovidov)。hasColumnInTable函数不再接受用于在任意远程服务器上检查列的可选参数hostname、username和password;仅保留hasColumnInTable(database, table, column)形式。被移除的远程模式存在安全隐患:它允许任何用户向任意主机发起出站连接,会将凭证泄露到查询日志中,而且不受任何特权约束。#110881 (alexey-milovidov).PostgreSQL和MaterializedPostgreSQL数据库引擎现在会遵循服务器的remote_url_allow_hosts配置,与PostgreSQL表引擎、postgresql表函数以及通过 DDL 创建的字典的现有行为保持一致。该策略在执行CREATE DATABASE以及用户发起的ATTACH DATABASE时生效:如果服务器上配置了remote_url_allow_hosts,那么创建或附加指向白名单以外主机的PostgreSQL或MaterializedPostgreSQL数据库时,将被拒绝并返回UNACCEPTABLE_URL错误。已有的数据库在服务器启动时仍会正常加载,因此升级不会导致服务器无法启动。#111135 (alexey-milovidov).- 移除了
Arrow和ArrowStream格式中基于 Apache Arrow 库的读取器和写入器。ClickHouse 原生实现自 26.7 起即为默认实现,现已成为唯一实现。设置input_format_arrow_use_native_reader和output_format_arrow_use_native_writer已废弃:它们仍可被接受,但不再起作用,因此原先将其设为0以强制使用 Apache Arrow 实现的查询,现在将改用原生实现。#111996 (alexey-milovidov). - MySQL 数据源的 TLS 凭证 (
ssl_ca、ssl_cert、ssl_key) 不能再通过 SQL 以文件路径形式指定——无论是在通过CREATE NAMED COLLECTION创建的命名集合中、作为查询参数,还是在CREATE DICTIONARY查询中——因为服务器会以自身权限打开这些文件。服务器配置文件中仍支持使用路径。在其他场景中,请通过新增的ssl_ca_pem、ssl_cert_pem和ssl_key_pem参数传入证书或密钥的内容,这些参数会像密码一样在日志和SHOW查询中被脱敏处理。#112070 (alexey-milovidov). disable_insertion_and_mutation现在会阻止Kafka、RabbitMQ和NATS表的后台消费,但仍允许直接写入外部存储。受此限制的Kafka2、NATS和RabbitMQ表在直接执行SELECT时不会初始化消费者。新近引入的message_queue_disable_insertion设置现在需要重启服务器才能生效。#113660 (cwurm).- 对
AggregateFunction列执行窗口PARTITION BY或ORDER BY现在会被拒绝并返回ILLEGAL_COLUMN错误,与对此类列执行顶层ORDER BY的现有行为一致。此前,此类查询至少会被一种分析器接受,且窗口PARTITION BY的分区结果会随max_threads的取值而变化。该限制同样适用于嵌套在Array、Tuple、Map、Variant或SimpleAggregateFunction中的状态。基于普通类型的SimpleAggregateFunction、QBit,以及对状态执行的GROUP BY和DISTINCT均不受影响。#113878 (groeneai). - 修复了
SYSTEM ... CACHE ON CLUSTER命令的访问检查。此前这些命令要求的是SYSTEM DROP CACHE特权组,而非各命令对应的单项特权:一方面,仅持有某项细粒度缓存特权的用户会被拒绝;另一方面,持有该特权组的用户即使不具备SYSTEM SYNC FILESYSTEM CACHE特权,也能执行SYSTEM SYNC FILESYSTEM CACHE ON CLUSTER。#114042 (groeneai). NATS表引擎现可通过新增的nats_credentials设置以内联方式传入凭证 (载荷内容与.creds文件相同) ,并且不再允许在 SQL 中指定nats_credential_file:该路径指向服务器文件系统上的文件,而服务器会以自身的特权打开该文件,因此该路径只能在服务器配置文件中定义的命名集合中指定,或在服务器配置中通过nats.credential_file指定。查询可以使用内联的nats_credentials覆盖此类已配置的路径,除非运维人员已通过<nats_credential_file overridable="false">将其锁定。在此限制引入之前创建的表,升级后仍可正常使用。#114644 (alexey-milovidov)。
数据类型与格式变更
- 对于存储在对象存储上的备份 (即直接使用
S3(...)/AzureBlobStorage(...)目标端,以及底层为 S3 或 Azure 的Disk(...)目标端) ,BACKUP和RESTORE均不再支持zip/zipx备份归档格式。Zip 需要随机定位才能读取其中央目录,而这在对象存储上非常缓慢。请改用基于 tar 的格式,例如tar.gz。#101770 (Onyx2406)。 - 将
DateTime64的支持范围从[1900-01-01, 2299-12-31]扩展到[0000-01-01, 9999-12-31]。超出原有范围的值现在会 (通过 cctz) 正确计算,而不再被截断到边界值。当 precision 为 8 或 9 时,由于刻度值以Int64存储,范围仍然较窄 (在纳秒精度下,最大值仍为2262-04-11) 。向后兼容性:如果您之前使用过超出范围的日期时间值,并依赖旧范围内非常特定的饱和规则,请注意现在的结果会有所变化,且更加准确。#107907 (alexey-milovidov)。 - 在
JSONEachRow及类似格式中,DateTime64/DateTime列中未加引号的 JSON 数字现在会被解释为 Unix 时间戳 (自纪元起的秒数) ,并可带有子秒级精度,与Values格式、CAST和toDateTime64的行为保持一致。此前,带有小数部分的数字 (例如1703363853.035) 会被拒绝并报错CANNOT_PARSE_INPUT_ASSERTION_FAILED,而纯整数 (例如1703363853) 会被读取为DateTime64的原始缩放值,从而得到1970-...的时间戳。对于写入DateTime64列的未加引号整数,这是一项向后不兼容的变更;带引号的字符串以及 ClickHouse 自身 (始终带引号) 的 JSON 输出不受影响。#108091 (alexey-milovidov)。 - 实验性的
ALP编解码器现在使用Float64执行Float32的缩放运算,从而消除了处理十进制数据时出现的异常,并显著提升了压缩率。#111627 (rienath)。 - 拒绝换算为 Int64 微秒时会溢出的时间跨度设置值 (毫秒/秒) #112757 (azat)。
- 异步指标现在支持
Map数据类型,按 CPU 核心和按设备划分的指标已合并为单个键值指标:OSUserTimeCPU0、OSUserTimeCPU1……合并为单个OSUserTimeCPU指标,其值为 CPU 核心编号到对应值的映射 (其他OS*TimeCPU*指标、CPUFrequencyMHz_*、Temperature*、EDAC*、Block*_*、Network(Receive|Send)*_*、Disk*_*、*BlobsQueueEstimate和AsyncLogging*QueueSize同理) 。system.asynchronous_metrics新增了key_values Map(LowCardinality(String), Float64)列 (此类指标的value列为NaN) ;system.asynchronous_metric_log通过新增的key列,按每个键一行记录这些指标;Prometheus 端点以标签形式导出这些指标 (例如ClickHouseAsyncMetrics_BlockReadBytes{device="sda"}) ;GraphiteMetricsTransmitter则以<prefix>.<Metric>.<key>的形式发送。如果您的监控系统读取的是旧指标名称,请将asynchronous_metrics_key_values_mode设置为legacy_names以保留旧名称,或在迁移期间设置为both;该服务器设置可通过SYSTEM RELOAD CONFIG生效,无需重启。#115333 (alexey-milovidov)。#116791 (alexey-milovidov)。 - 对象存储磁盘现在默认使用原生元数据存储事务,从而提升了元数据更新的一致性。#89658 (Michicosun)。
设置与配置变更
- 移除了早已弃用的函数
snowflakeToDateTime、snowflakeToDateTime64、dateTimeToSnowflake和dateTime64ToSnowflake。这些函数早在 v24.6 中就已弃用,取而代之的是snowflakeIDToDateTime、snowflakeIDToDateTime64、dateTimeToSnowflakeID和dateTime64ToSnowflakeID,请改用后者。设置allow_deprecated_snowflake_conversion_functions(此前用于重新启用这些函数) 现已过时,不再起任何作用。#108711 (alexey-milovidov)。 - 将
Date32的支持范围从[1900-01-01, 2299-12-31]扩展至[0000-01-01, 9999-12-31],与DateTime64保持一致。解析和类型转换现在支持扩展后的范围,不再静默截断到旧的边界值。向后兼容性说明:在数值转换toDate32(N)中,[120530, 2932896]范围内的值现在会被解释为天数 (对应2300-01-01至9999-12-31之间的日期) ,而不再被视为 1970 年初的 Unix 时间戳。这与“凡落在天数范围内的数字均视为天数”的规则一致;小于0000-01-01对应天数的数字,以及晚于9999-12-31的时间戳,将被截断到新的边界值。#111534 (alexey-milovidov)。
其他向后不兼容的变更
arrayIntersect和arraySymmetricDifference不再将同一参数内重复出现的值视为在多个参数中出现。依赖先前行为的查询现在可能返回不同的结果:arrayIntersect([1], [2], [1, 1])返回[]而非[1],arrayIntersect([1, 2], [2], [1, 1, 2])返回[2]而非[1, 2],arraySymmetricDifference([1], [2], [1, 1])返回[2, 1]而非[2]。对于arraySymmetricDifference,只需两个参数即可出现差异:arraySymmetricDifference([1], [2, 2])返回[2, 1]而非[1]。现在,只有当某个值在当前参数之前的每个参数中都存在时,才会为当前参数计数,因此结果恰好包含所有参数中共有的值。此外,arrayIntersect现在仅基于最小的参数构建哈希表,而不再基于所有参数构建;当各参数大小差异较大时,速度最高可提升 1.85 倍,内存占用减少三分之一。arrayUnion不受影响。#113021 (alexey-milovidov) 。- 弃用
minmax列统计信息类型。#108680 (hanfei1991) 。 - 修复
SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER的访问权限检查:此前它错误地要求SYSTEM PREWARM MARK CACHE特权,而非SYSTEM PREWARM PRIMARY INDEX CACHE特权。#109198 (Algunenano) 。 - 修复了
SYSTEM STOP/START CLEANUP和SYSTEM STOP/START VIRTUAL PARTS UPDATE ON CLUSTER错误地要求SYSTEM PULLING REPLICATION LOG特权,而非SYSTEM CLEANUP/SYSTEM VIRTUAL PARTS UPDATE特权的问题。#110289 (groeneai) 。 /通配符 (匹配任意层级的目录) 现在也能匹配当前目录本身。此前,通配符模式中的/未被作为特殊情况处理,因此data/**/file.txt无法匹配data/file.txt(零层目录) 。#97676 (alexey-milovidov) 。
新功能
函数与数据类型
- 新增
parseQueryToJSON和formatQueryFromJSON函数,用于将 AST 序列化为 JSON 以及从 JSON 反序列化为 AST;同时新增实验性的clickhouse_json方言,可通过enable_json_ast_dialect启用。#100412 (alexey-milovidov)。#113480 (fm4v)。 - 新增系统表
system.stemmers,用于列出stem函数可指定的所有词干提取器语言。#100611 (Ergus)。 - 新增对标准 SQL
AT TIME ZONE和AT LOCAL后缀运算符的支持,作为toTimeZone的语法糖。现在,表达式expr AT TIME ZONE zone等价于toTimeZone(expr, zone),expr AT LOCAL等价于toTimeZone(expr, timeZone())。#106092 (lvzhipin03)。 URL表引擎和url表函数现在会根据 URL scheme 将请求分派到相应的后端:file://由File引擎处理,s3:///gs:///gcs:///oss://由S3处理,az:///azure:///abfss:///abfs://由AzureBlobStorage处理,hdfs://由HDFS处理,http(s)://则仍与以往一样由URL引擎处理。url_base设置会在 scheme 分派之前生效。仅默认url_scheme_mappers所解析的 S3 scheme 会被分派;其他兼容 S3 的厂商 scheme (cos、obs等) 不会被分派,需直接使用s3引擎/函数。#106093 (alexey-milovidov)。- 新增
dotProductTransposed函数 (别名scalarProductTransposed) ,用于计算QBit列与参考向量之间的近似内积,作为对现有L2DistanceTransposed和cosineDistanceTransposed函数的补充。#108100 (alexey-milovidov)。 - 为
QBit数据类型新增可选的 stride 参数 (QBit(T, dimension, stride)) ,可将维度分组存储在独立的流中,使向量搜索能够高效地仅读取前若干个维度 (例如适用于 Matryoshka 嵌入向量) 。转置距离函数新增可选的第四个参数used_dims,用于只读取部分维度。#108103 (alexey-milovidov)。 QBit数据类型新增对Int8元素类型的支持,从而可对量化后的 8 位整数向量进行存储和转置距离向量搜索 (L2DistanceTransposed、cosineDistanceTransposed) 。#108105 (alexey-milovidov)。- 新增函数
randomHadamardTransform(vector[, seed[, output_dims]]):对浮点向量执行确定性的随机化 Hadamard 变换。这是一种正交且保持范数的旋转,可用于在量化前对嵌入向量进行预处理;截断后还可用作 Johnson–Lindenstrauss / 子采样随机化 Hadamard 随机投影。#108227 (alexey-milovidov)。 - 实现聚合函数
mergedJSONPatch,用于对 JSON 值进行 RFC 7396 风格的 merge-patch 聚合,支持状态合并,并可在 AggregatingMergeTree 中使用。用户可以将时间戳或其他排序列作为排序键对 JSON 列进行聚合,从而计算出最新状态。#108349 (larryluogit)。 - 新增函数
xxHash64Spark,该函数使用种子42为String和NULL输入计算与 Spark 兼容的xxHash64值,并返回Int64。#108436 (lalitium)。 - 新增
digits(n, offset[, length])函数,用于返回n中从索引offset(1-indexed)处开始、共length位的数字。如果未指定length,则返回从 offset 处直到末尾的数字。#109012 (1000ms)。 - 新增
sqr算术函数,用于计算数值的平方。#109061 (lalitium)。 - 新增量化转置距离函数
cosineDistanceTransposedQuantized、L2DistanceTransposedQuantized和dotProductTransposedQuantized,这些函数作用于由quantizeBFloat16ToInt8Lloyd-Max 编码构成的QBit(Int8),并在计算时实时对已存储的编码进行反量化。浮点参考向量作为全精度查询向量,以Float32precision 进行比较 (Float64查询向量会被收窄) ;Array(Int8)参考向量本身也会被反量化,从而计算对称的量化对量化距离。#109405 (alexey-milovidov)。 - 新增函数
dictGetRoot,用于返回层级字典中某个键的最顶层祖先 (即根节点) ,可作为dictGetHierarchy(dict_name, key)[-1]的便捷替代写法。#109459 (alexey-milovidov)。 - 新增
mergeTreeCodecBlockCounts(database, table)表函数,可按MergeTree表的 (分片、列、子流) 维度,统计使用各编解码器的压缩块数量。#109623 (rienath)。 - 新增函数
notHas,作为has在数组、map 和 JSON 上的取反形式。当被查找对象为常量数组时,optimize_rewrite_has_to_in(默认启用) 会将notHas(constant_array, x)重写为x NOT IN constant_array,从而通过集合查找执行,并可像NOT IN一样利用主键索引进行裁剪。#109926 (nihalzp)。 - 新增
MultiPoint地理数据类型,以Array(Point)形式存储,并已纳入Geometry类型。#109951 (davidmenggx)。 - 函数
arrayElement(即vec[n]运算符) 和arraySlice现已支持QBit数据类型:qbit[n]以全精度返回第 n 个向量元素,arraySlice(qbit, offset, length)返回在部分维度上的投影。两者都只读取所需 stride 组的比特平面,且与 stride 组边界对齐的切片会直接复用已存储的流,无需复制。#109953 (Utkal059)。 - 为文本索引和
tokens函数新增splitByRegexp分词器。它以正则表达式作为分隔符将输入拆分为标记,例如tokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'),从而可以保留C++、C#等包含特殊字符的标记,避免像其他分词器那样将其拆开。#110002 (Ergus)。 - 新增函数
geometryIntersectCartesian和geometryIntersectSpherical,用于判断两个几何对象是否相交。与polygonsIntersectCartesian/polygonsIntersectSpherical不同,这两个函数支持任意几何数据类型 (Point、LineString、MultiLineString、Ring、Polygon、MultiPolygon) ,包括通用的Geometry类型,且两个参数的类型可以不同。#110062 (alexey-milovidov)。 - 原生 ORC 读取器现已支持 ORC 的
uniontype,并将其映射为 ClickHouse 的Variant类型 (此前此类列会因Unsupported ORC type而被拒绝) 。#110078 (alexey-milovidov)。 - 原生 ORC 输出格式现已支持写入 ClickHouse 的
Variant类型,并将其映射为 ORC 的uniontype(此前会报错ILLEGAL_COLUMN) 。#110085 (alexey-milovidov)。 - 新增帧格式,可通过新设置
framing_output_format选择:帧格式会将查询响应的各个部分复用到单个 HTTP 响应流中,包括数据块、总计值和极值、进度数据包、性能事件、服务器日志以及异常。目前已实现的帧格式有:None(默认值,行为与之前完全一致) 、EventStream(HTTP 服务器发送事件) 、JSONEachPacketBase64和JSONEachPacketString(每个数据包对应一个 JSON 对象,数据分别以 base64 编码或字符串形式表示) 。#110127 (alexey-milovidov)。 - 新增
bigquery表函数和BigQuery表引擎,用于读写 Google BigQuery 表 (包括公共数据集) 。表结构会根据 BigQuery 表的 schema 自动推断。身份验证支持 OAuth 访问令牌、JSON 格式的服务账号密钥,以及带刷新令牌的 OAuth 客户端。#110166 (alexey-milovidov)。 - 新增函数
aiRedact,借助 LLM 提供商检测文本中的个人身份信息 (PII) 并进行脱敏。可指定需要脱敏的类别 (例如['email', 'name']) ,也可传入空数组以使用默认的 PII 类别集合。匹配到的值会被替换为标记 (默认为[REDACTED]) 。#110464 (davidmenggx)。 - 新增
aiFilter函数,借助 LLM 判断文本是否满足自然语言描述的条件,并返回UInt8,可用于WHERE、PREWHERE和JOIN ... ON。#110594 (ylw510)。 PostgreSQL表引擎、postgresql表函数、PostgreSQL和MaterializedPostgreSQL数据库引擎以及PostgreSQL字典现已支持通过 TLS/SSL 连接 PostgreSQL:支持sslmode以及证书和私钥,二者既可以直接以内容形式提供 (sslrootcert_pem、sslcert_pem、sslkey_pem;会像密码一样进行掩码处理) ,也可以以路径形式提供 (sslrootcert、sslcert、sslkey;仅可在服务器配置文件中定义的命名集合中指定) 。#110615 (alexey-milovidov)。postgresql表函数和PostgreSQL表引擎现在可以通过 PostgreSQL 协议连接到另一台 ClickHouse 服务器 (仅限指定表名的情况;暂不支持query(...)形式) 。新增 PostgreSQL 兼容函数format_type和current_setting。#110760 (alexey-milovidov)。- 新增函数
aiSimilarity,使用嵌入模型计算两段文本之间的语义相似度。返回[-1, 1]范围内的Nullable(Float32)值,其中1表示两段文本完全相同;若某个操作数为NULL/空值,或其嵌入计算失败,则返回NULL。#110777 (davidmenggx)。 - 新增
Remote和RemoteSecure数据库引擎,可实时访问远程 ClickHouse 服务器上某个数据库中的表,并将SELECT和INSERT查询转发至该服务器。它们相当于MySQL和PostgreSQL数据库引擎在 ClickHouse 之间互访场景下的对应实现。#110975 (alexey-milovidov)。 - SQL 查询支持管道运算符:
FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10,与 GoogleSQL 的管道语法类似。任何SELECT查询之后都可以接一串|>运算符,每个运算符都会将其前面的查询包装为子查询,因此生成的 AST 与使用嵌套子查询的等效查询相同。在以FROM子句开头的查询中,SELECT子句现在可以省略,默认为SELECT *。#111151 (alexey-milovidov)。 - 新增聚合函数
gini,用于计算有限非负数值的基尼系数,支持分组聚合和分布式聚合。#112280 (amirreza1307)。#114643 (groeneai)。 PNG输出格式支持动画 PNG。通过t列可将查询结果生成为动画,t的时间刻度由output_format_image_time_multiplier_seconds和output_format_image_time_divisor_seconds设置;启用output_format_image_streaming_animation后,帧会在查询生成时即时写出,而不是缓存在内存中。#112846 (alexey-milovidov)。- 在
system.mutations中新增finish_time列,用于记录变更的完成时间。对于未完成的变更以及完成时间未知的变更,该列值为零。#113474 (nikitamikhaylov)。 - 为
system.metric_log新增bucketed模式类型,它采用包含 128 个桶的分桶Map序列化,将所有指标存储在单个Map(Enum16(...), Int64)列中,并为每个指标提供一个ALIAS列以保持兼容:该表仅由少量列组成,而非数千列;零值不会被存储;读取单个指标时只需读取 128 个桶中的一个。此外,键为Enum的Map现在可以通过枚举值的字符串名称进行索引,例如map['name']。#115380 (alexey-milovidov)。 - 为
tokens函数和MergeTree文本索引新增chinese分词器。它使用字典和隐马尔可夫模型 (算法参考 jieba) 对中文文本进行分词,支持coarse_grained(默认) 和fine_grained两种粒度。#89945 (amosbird)。 - 新增
groupFormat聚合函数,使用指定的输出格式对每个分组中的行进行格式化,并以字符串形式返回结果。#93201 (wandersofb)。 - 新增聚合函数组合器
-Tuple,它将底层聚合函数分别独立应用于Tuple列的每个元素,并以Tuple形式返回各结果,同时保留元素名称:对于t = (a, b),sumTuple(t)返回(sum(a), sum(b))。对于有多个参数的聚合函数,每个参数各传入一个 tuple,并按位置一一配对:corrTuple((a1, a2), (b1, b2))返回(corr(a1, b1), corr(a2, b2))。与作用于数组的-ForEach不同,各元素的类型可以不同,且每个元素的结果类型和名称均会保留。#98190 (RinChanNOWWW)。
SQL 与查询功能
- 新增在 projection 定义中支持 WHERE 子句。带有 WHERE 的 projection 仅物化满足谓词条件的行;当查询的 WHERE 条件蕴含 projection 的 WHERE 条件时,优化器可基于代价选择使用这些 projection。#102347 (SBALAVIGNESH123)。
- 新增在 HTTP 接口中通过 URL 路径访问表和数据库的方式 (例如 `/database/table.format.gz?filter=a>0`) ,并新增一系列设置 (`http_allow_database_as_path`、`http_allow_table_as_file`、`http_allow_filters_as_path`、`http_allow_filters_as_unrecognized_url_parameters`、`select`、`order`、`sort`、`filter`、`page`、`compression`、`format`、`input_format`、`output_format`、`default_format`、`database`) ,这些设置既可相互组合,也可与现有的 `query` URL 参数搭配使用。#105249 (alexey-milovidov)。
- 新增
Remote和RemoteSecure表引擎,即remote和remoteSecure表函数的持久化版本。现在除CREATE TABLE ... AS remote(...)外,也可使用CREATE TABLE ... ENGINE = Remote('addresses', db, table, ...)。#106189 (alexey-milovidov)。 - 新增用于分析查询性能的
EXPLAIN ANALYZE:该命令会实际执行查询,并以熟悉的查询计划格式展示实际的执行指标。#106586 (Fgrtue)。#110668 (Fgrtue)。 - 新增与引擎无关的
SYSTEM STOP、SYSTEM START、SYSTEM PAUSE、SYSTEM CANCEL和SYSTEM REFRESH命令,以及作用于整个服务器的... ALL BACKGROUND形式,可通过统一的接口控制Kafka、RabbitMQ、NATS、S3Queue/AzureQueue表以及可刷新 materialized view 的后台活动。对于可刷新 materialized view,这些命令是现有SYSTEM ... VIEW命令的别名。为在 NATS 上支持这些控制,JetStream 表现在仅在插入成功后才确认消息 (至少一次语义;此前消息在投递时即被自动确认,一旦插入失败便可能丢失) 。新增nats_wait_for_flush_interval设置 (默认false,保持此前的低延迟行为) ,启用后会在整个刷写时间间隔内保持消费周期开启,而不是在队列清空后立即刷写。新增nats_commit_on_select设置,启用后直接对 JetStream 表执行SELECT会消费 (确认) 所读取的消息。#107476 (NIKTONIKTO717)。 mysql、postgresql和sqlite表函数及表引擎现支持接收用户自定义查询 (而非表名) ,并将其原样传递给外部数据库,写法可以是子查询(SELECT ...),也可以是query('SELECT ...')。结果表的结构根据查询结果推断,且此类表为只读。#107740 (alexey-milovidov)。- 引入
QueryRunner表引擎。插入QueryRunner表的每条记录都代表一个由该引擎执行的查询。该引擎可用于异步执行查询、批量执行生成的查询、将查询路由到远程集群、基准测试、模糊测试,以及基于影子流量的测试。#107888 (mstetsyuk)。 - 窗口函数支持
GROUPS窗口帧模式 (SQL:2011) ,例如any(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING)。在GROUPS窗口帧中,边界以完整的对等组为单位计数 (对等组即在ORDER BY键上取值相同的一组行) ,因此N PRECEDING/N FOLLOWING表示当前行所在对等组之前/之后的N个对等组,而非物理行数 (ROWS) 或ORDER BY值的距离 (RANGE) 。#108653 (nihalzp)。 - 普通的
CREATE MATERIALIZED VIEW ... POPULATE现在具备本地原子性:视图订阅源表的新插入数据与对现有数据创建快照这两个操作,会在源表上的一个短暂排他锁内一并完成,因此在填充期间通过同一服务器并发插入的行不会再被遗漏或重复 (新增设置materialized_views_populate_atomically,默认启用) 。该保证仅覆盖本地插入路径——到达其他副本或经由分布式写入路径的插入不在保证范围内——且要求源表能够提供固定快照 (MergeTree系列和Memory) ;对于其他源表,以及CREATE OR REPLACE/REPLACE和在Replicated数据库中创建的视图,仍沿用原有的非原子填充方式。此外,POPULATE现在也可以与TO搭配使用,用于回填目标表。#108715 (alexey-milovidov)。 ALTER USER、ALTER ROLE和ALTER SETTINGS PROFILE现在支持将SET name = value作为MODIFY SETTING name = value的别名。该语法仅就地修改指定的设置,其余设置保持不变;而单独使用的SETTINGS子句则会替换整个设置列表。这样可以降低误清除用户其他设置的风险。#108722 (groeneai)。- 支持
ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK expr,可就地修改现有约束的表达式。#108768 (alexey-milovidov)。 - 新增基于排序的 IEJoin 算法,适用于
ON子句中在被连接表之间包含两个不等式比较 (<、<=、>、>=) 的连接,在join_algorithm设置中添加ie_join即可启用。支持的连接类型包括ALL INNER/LEFT/RIGHT/FULL JOIN和SEMI/ANTILEFT/RIGHT JOIN。此前,此类查询会以带过滤条件的CROSS JOIN方式执行 (仅支持INNER) ,在大表上速度要慢得多。#109920 (vdimir)。 - 新增系统表
system.user_query_log,每个用户都可以通过它查看自己的查询日志记录,而无需拥有查询日志表的访问权限。最初的构想与实现出自 Yue Ni (@niyue)。#110156 (alexey-milovidov)。 - 新增设置
run_query_in_background。启用后,服务器接收查询后会立即返回空结果,并且无论连接状况如何,都会将查询执行完毕,执行结果将被丢弃。可通过query_id在system.processes和system.query_log中跟踪该查询。适用于INSERT ... SELECT、CREATE TABLE … AS SELECT或CREATE MATERIALIZED VIEW … POPULATE等不应因连接断开而中止的长时间运行查询。#112816 (mstetsyuk)。 - 支持 ALTER TABLE … MODIFY PROJECTION,可修改现有 projection 的 projection 级别设置 (例如 index_granularity) ,而无需重建该 projection。新设置会在后续合并过程中以惰性方式生效。#113343 (diegomestre2)。
- 面向数据湖的 S3 tables 引擎目录现在不仅支持查询现有表,还支持
INSERT。#113505 (scanhex12)。 Iceberg目录现已支持通过catalog_type = 'horizon'接入 Snowflake Horizon Catalog,可读写由 Snowflake 托管的Iceberg表。#114547 (melvynator)。- 新增
skip_unavailable_shards_mode设置 (也可作为Distributed引擎设置使用) ,用于在启用skip_unavailable_shards时控制静默忽略远程分片的哪些异常,从而在分布式环境中更精细地控制查询行为。#79091 (byte-sourcerer)。
存储、数据湖和对象存储
- 新增对 Puffin 文件格式的支持 (https://iceberg.apache.org/puffin-spec/) 。现在可以在
file、url、s3等表函数中使用该格式。#103936 (scanhex12)。 - 为
MergeTree表新增 “packed” 数据分区片段存储方式,将一个 part 的所有文件存入单个归档文件 (data.packed) ,而不是每个 stream 各对应一个文件。该功能由min_bytes_for_full_part_storage、min_rows_for_full_part_storage和min_level_for_full_part_storage设置控制,默认禁用。兼容性说明:表一旦写入 packed parts,旧版本服务器便无法读取,因此启用此格式后将无法降级服务器。#108118 (Algunenano)。 - 为 NATS 表引擎新增
nats_credentials设置,允许用户以字符串形式内联指定 NATS 凭证 (内容与.creds文件的载荷一致) 。#110733 (addshore)。
数据格式与摄取
- 新增
HiveText输出格式,以 Apache HiveLazySimpleSerDe文本形式写入数据。字段以\x01分隔,行分隔符由新增的format_hive_text_rows_delimiter设置指定 (默认为\n) ,嵌套的Array、Map和Tuple值则使用 Hive 的分隔符列表。该输出格式以 Hive 默认的LazySimpleSerDe为目标;对于嵌套值或自定义行分隔符,它与 ClickHouse 的HiveText输入格式并不对称。#107582 (alexey-milovidov)。 - 新增
GeoJSON输出格式,用于写入每行对应一个 feature 的 GeoJSONFeatureCollection文档。新增的format_geojson_validate_geometry设置 (默认启用) 会在读取和写入时校验 GeoJSON 几何形态;此外,GeoJSON输入格式现在会将id推断为Nullable(String),从而将缺失或为null的 ID 与空字符串区分开来。#108065 (nihalzp)。
设置、访问与可观测性
- 新增内置文档搜索页面,可通过 HTTP 接口的
/docs路径访问,支持对system.documentation表进行即时搜索,并可渲染参考文档 (支持语法高亮、数学公式和交叉链接) 。#108345 (alexey-milovidov)。 - 新增基于 MeCab 形态分析器的日语分词器,可用于文本索引以及 tokens/hasAnyTokens/hasAllTokens 函数。字典在运行时从服务器配置中指定的位置加载,并在使用前通过 SHA-256 校验和进行校验。#111420 (Ergus)。
- 新增文件系统缓存设置
system_cache_extensions,用于在启用use_split_cache时控制哪些文件存储在系统缓存中。#111575 (kirillgarbar)。 - 新增
always_fetch_mutated_part设置,允许副本直接从其他副本下载已变更的 parts,而无需在本地执行变更。#113020 (rorylshanks)。
其他新功能
- 负数
LIMIT现已支持WITH TIES。#100930 (nihalzp)。 - 新增
restore_table_data、restore_access_entities和restore_functions恢复设置,用于精细控制要恢复的内容。这些设置可按类别分别覆盖structure_only,例如structure_only=true, restore_access_entities=true会恢复表定义和访问实体,但不恢复表数据。#102402 (fm4v)。 - 现在可以在字典定义中通过
dictionary_lazy_load为单个字典配置延迟加载,以覆盖全局服务器设置dictionaries_lazy_load。这样即可让部分字典延迟加载,其余字典则立即加载。#108314 (mstetsyuk)。 - 数组下标运算符支持以整数数组作为索引:
arr[indexes]返回所有指定位置上的元素,等价于arrayMap(i -> arr[i], indexes)。#108371 (ucasfl)。 - 新增函数
geoToUTM、UTMToGeo、geoToMGRS和MGRSToGeo,用于在 WGS84 地理坐标与 UTM、MGRS 坐标系之间相互转换。#108939 (alexey-milovidov)。 - 新增
SYSTEM UNLOAD DICTIONARY和SYSTEM UNLOAD DICTIONARIES命令,可在不删除字典定义的前提下释放字典占用的内存。字典将在下次访问时延迟重新加载。#109639 (Manerone)。 - 为文本索引以及
tokens、hasAnyTokens和hasAllTokens函数新增icu分词器,提供可感知区域设置的 Unicode 词语分割 (包括针对中文、日文、泰文等语言的基于字典的分割) 。#109940 (Ergus)。 - 新增编解码器
ZXC——一种非对称 LZ 编解码器,压缩较慢但解压缩极快,压缩率介于LZ4和ZSTD之间。#110620 (alexey-milovidov)。 - 新增
s3_base设置,使s3、s3Cluster、gcs和oss表函数以及S3表引擎中的相对 URL 能够基于 S3 基础 URL 进行解析。新增URL数据库引擎,可基于可选的基础 URL 将表名解析为 URL,并将其分派到相应的后端。#111512 (alexey-milovidov)。 url()和URL引擎现支持通配符展开,其方式是列出 HTTP 索引页 (HTML 或纯文本目录列表) 并提取匹配的 URL。通配符针对 URL 路径组件进行匹配,并对索引页大小和读取的目录数量设有上限。#95181 (niyue)。kafka_sasl_mechanism新增支持值AWS_MSK_IAM,使 ClickHouse 能够使用 IAM 角色向 Amazon MSK 进行身份验证,无需管理 SASL/SCRAM 凭证。#96100 (kalavt)。- 为文本索引新增后处理器,用于在标记化之后对标记进行转换。#98939 (Ergus)。
Experimental 功能
查询规划与执行
- 为可执行的用户自定义函数新增了”驱动程序”。在
<user_defined_executable_function_drivers_config>中声明的驱动程序可用于CREATE FUNCTION name ARGUMENTS (...) RETURNS T ENGINE = DriverName(...) AS '...code...',在创建函数时编译或以其他方式处理用户代码片段,并生成可运行的可执行 UDF。生成的配置存储在<dynamic_user_defined_executable_functions_path>中,原始查询则以ATTACH FUNCTION的形式持久化,因此函数在服务器重启后依然可用。作为概念验证,c_function_body驱动程序会以executable_pool模式在沙箱化的 Docker 容器中编译并运行 C 函数体。#105131 (alexey-milovidov)。 - 发往
/api/v1/query和/api/v1/query_range的 Prometheus Query API 请求现在会记录到system.query_log中,并包含read_rows和read_bytes指标。#106611 (JTCunning)。 - 启用
make_distributed_plan时,支持对 MergeTree 家族表执行SELECT ... FINAL的分布式查询计划读取。#108148 (davenger)。 - 为 MergeTree 查询新增实验性的、基于查询计划的并行副本执行方式。#108504 (devcrafter)。
- 新增实验性表函数
eval,它将常量表达式求值为查询字符串,并执行由此得到的单个SELECT查询。该功能默认禁用,可通过设置allow_experimental_eval_table_function启用。作者:Yue Ni #110132 (alexey-milovidov)。 - 基于查询计划的并行副本 (
parallel_replicas_plan_based) :本地/远程边界现在由作用于常规查询计划的计划级优化来确定;对包含UNION的视图的查询,无需启用parallel_replicas_allow_view_over_mergetree即可并行执行。使用IN (subquery)的查询现在会回退到本地查询计划,而不再直接报错。#111063 (devcrafter)。#112443 (devcrafter)。 - 增强实验性 AI 函数的安全性:默认拒绝指向远程主机的不安全 (
http) 端点 (新增设置ai_function_allow_insecure_endpoint) ,默认限制每个查询的出站 API 调用次数 (ai_function_max_api_calls_per_query现默认为1000) ,并对写入日志的提供方错误响应进行脱敏处理。#111286 (george-larionov)。 - 基于查询计划的并行副本 (
parallel_replicas_plan_based) 现在可以分布式执行符合条件的 JOIN (INNER、LEFT、RIGHT,包括SEMI/ANTI) :整个连接在同一个分布式查询计划片段中执行,其中一侧由各副本协同处理,另一侧则进行广播。#112268 (devcrafter)。 - 分布式查询 (
make_distributed_plan = 1) 被取消时,会报告导致取消的具体错误,而不再只返回QUERY_WAS_CANCELLED。此前,失败的工作线程任务的真实错误只能在服务器日志中查看。#112590 (davenger)。 - 支持分布式执行包含
IN (subquery)的查询计划,而无需将其改写为JOIN。该集合仅在发起节点上构建一次,其值随工作线程任务一并下发。移除了对rewrite_in_to_join的强制覆盖;该改写仍可通过显式设置启用。#113826 (davenger)。 - 分布式查询计划 (
make_distributed_plan) 现在会在满足LIMIT后停止其上游阶段,而不再先计算出完整结果再将其丢弃。#114806 (davenger)。 - 修复了 PromQL 查询在范围选择器中使用
offset(例如rate(m[2m] offset 5m)) 时出现的错误Illegal type Decimal(18, 0) of argument of function toIntervalNanosecond。#114997 (nikitamikhaylov)。 - 由 Cascades 优化器构建的分布式查询计划现已支持
GROUPING SETS聚合 (make_distributed_plan = 1, enable_cascades_optimizer = 1) 。#115426 (davenger)。 TimeSeries表现在可以维护一张“最近样本”表:当新的引擎设置recent_samples_ttl_seconds不为零时,引擎会为样本表创建一个带生存时间 (TTL) 的副本 (按recent_samples_partition_by分区,默认按天分区) ,每次插入时都会同步写入;时间范围落在生存时间 (TTL) 窗口内的 PromQL 查询会自动从该副本读取数据,使大表上的告警/记录规则以及短时间范围仪表盘的速度提升数倍。可通过新的查询级别设置time_series_prefer_recent_samples_table关闭这一优先读取策略。#115441 (nikitamikhaylov)。- 分布式查询计划 (
make_distributed_plan) 现在会在LIMIT满足后及时停止空闲的上游阶段:空闲的 exchange sink 会在NoMoreDataNeeded到达后立即读取该信号,空闲的 exchange source 则会察觉其输出已关闭,并将停止信号转发给上游。此前,这些阶段会继续读取和计算无人消费的数据。#115690 (davenger)。 - 启用
parallel_replicas_plan_based后,自动并行副本功能现在可以收集运行时统计信息,并为受支持的查询启用并行副本。#115788 (devcrafter)。 - 新增面向分布式查询计划的实验性 Cascades 基于代价的优化器,可通过同时设置
enable_cascades_optimizer = 1和make_distributed_plan = 1启用。它会根据估算代价进行选择:join 策略可选 shuffle、broadcast、replicated 或本地 join;聚合方式可选两阶段、shuffle 或本地聚合;此外还支持两阶段分布式 top-N,以及并行读取和副本读取,并按需插入 exchange 算子。#86353 (davenger)。
存储、数据湖与索引
- 新增内存 SLRU 缓存,用于缓存反序列化后的 Paimon 元数据文件 (manifest 列表和清单) 。通过
use_paimon_metadata_files_cache设置启用后,对同一 Paimon 表的重复查询无需再从对象存储重新下载和解析元数据。#104657 (Binnn-MX)。 - Experimental
ReaderExecutor(use_reader_executor,默认关闭) 现在可以保持远程源连接处于打开状态,并在多次顺序读取之间复用该连接,从而减少扫描时的对象存储请求次数。#107735 (CheSema)。 - 为 Experimental
ReaderExecutor的读取路径 (use_reader_executor,默认禁用) 新增读穿透 (read-through) 文件系统缓存。#110029 (CheSema)。 - 新增实验性
MergeTree设置allow_experimental_adaptive_codec_selection。启用后,对于使用默认编解码器的列,合并和变更操作会针对每个数据块选择压缩后输出最小的编解码器。#111834 (rienath)。 - 为 Experimental
ReaderExecutor的读取路径 (use_reader_executor,默认关闭) 新增用户态页缓存层。缓存未命中时,executor 会将数据填充到用户态页缓存中,后续读取则以零拷贝方式直接从该缓存获取。#114890 (CheSema)。 - 现在可以通过
OPTIMIZE TABLE ... MANIFEST对Icebergmanifest 文件进行合并整理,以减少元数据文件数量。该功能需通过allow_experimental_iceberg_compaction设置启用。#98178 (SmitaRKulkarni)。
函数、格式与 AI
- Experimental:当谓词能将列精确划分为默认值与非默认值时,可直接利用
serialization.json中的按列稀疏性统计信息响应SELECT count(*) FROM t WHERE col <op> default(col),无需扫描任何数据。#105890 (Algunenano)。 - 新增 experimental 的
Quantize(...)向量编解码器系列,以及一种可选启用的两阶段近似向量搜索重写机制,该机制基于量化的伴随数据流运行。#108565 (shankar-iyer)。 - 重新启用 experimental 的
SZ3误差有界有损压缩编解码器,适用于Float32/Float64类型的列 (及其数组) 。需要启用allow_experimental_codecs。#108788 (alexey-milovidov)。 - 修复了读取经 experimental
SZ3('ALGO_LORENZO_REG', ...)编解码器压缩的数据时报CORRUPTED_DATA错误的问题,并避免了使用 experimentalSZ3编解码器压缩非有限浮点值 (NaN和无穷大) 时出现未定义行为。#110762 (alexey-milovidov)。 - PromQL:日期/时间函数 (
hour()、minute()、month()、year()、day_of_week()、day_of_month()、day_of_year()、days_in_month()) 现在可以不带参数调用,此时与 Prometheus 一致,默认使用vector(time())。#111869 (valerypetrov)。 - PromQL:修复了对不带标签的瞬时向量执行操作时因类型错误而失败的问题,例如
vector(1) + vector(2)、topk(1, vector(1))、label_replace(vector(1), ...)以及带on()的二元运算符。#111872 (valerypetrov)。 - PromQL:实现了
deriv函数,同时修复了在毫秒级分辨率时间戳下,其底层聚合函数的返回值偏小 1000 倍的缺陷。#112360 (valerypetrov)。 - 启用
parallel_replicas_plan_based时,对ORDER BY查询应用按序读取优化:排序操作现在会下发到各副本,再在发起服务器上合并,使每个副本都按 sorting key 顺序读取数据。同时修复了启用该设置后,对非主键列执行ORDER BY时报Unknown function __topKFilter的问题。#114315 (devcrafter)。 - 修复了重新加载数据分区片段后 (例如执行
ATTACH或重启服务器后) 的向量搜索读取问题:数据分区片段不再丢失其Quantized编解码器子列,因此搜索会读取量化子列,而不会回退到全精度列。#114763 (shankar-iyer)。 - experimental 的
TimeSeries表引擎不再对 samples 内部表中自动创建的value列应用Gorilla编解码器,这些列现在默认使用CODEC(ZSTD(1))。显式声明的列仍沿用用户指定的编解码器。timestamp列的默认设置保持不变 (CODEC(DoubleDelta, ZSTD(1))) 。#112110 (nikitamikhaylov)。#114790 (nikitamikhaylov)。 - 在以
make_distributed_plan = 1执行的查询中支持ROLLUP、CUBE、GROUPING SETS以及grouping函数。#114950 (davenger)。 - 为实验性的 ALP 编解码器新增 Real Doubles (RD) 变体,并支持可选参数
ALP(AUTO|STD|RD)。不带参数的 ALP 现在会在现有的 STD 方案和 RD 之间自动选择,不再固定使用 STD。#99654 (nazarii-piontko)。
其他 Experimental 功能
- 通过 kafka_partition_shard_num 和 kafka_shard_count 设置,为 StorageKafka2 添加静态的分区到分片亲和性,使多个 ClickHouse 分片能够以确定性的方式消费 Kafka 分区中互不相交的子集。#108886 (JingYanchao)。
- 现在可以通过
onelake_bearer_token设置,使用预先获取的 Bearer 令牌向 OneLake 进行身份验证,而无需使用onelake_client_id和onelake_client_secret,从而避免共享长期有效的客户端密钥。该令牌不会自动刷新,因此令牌过期后必须重新创建数据库。#109104 (asya-ch)。 - 修复了打包到
skp_idx.packed(通过packed_skip_index_max_bytes) 中的跳数索引的data_uncompressed_bytes值错误的问题:此前报告的未压缩大小实际上是压缩后的大小,这还可能导致distributed_index_analysis无法生效。#109272 (Algunenano)。 - 为实验性的 Prometheus 远程写入 v1 HTTP handler 添加了 Zstandard 压缩支持。#110907 (JTCunning)。
- PromQL:实现了函数
clamp、clamp_min、clamp_max和round。#111870 (valerypetrov)。 - PromQL:当分位数级别超出 [0, 1] 范围时,
quantile现在会与 Prometheus 一致,返回 -Inf/+Inf/NaN,而不再抛出错误;histogram_quantile现在也会与 Prometheus 一致,忽略le标签缺失或无法解析的输入序列。#111871 (valerypetrov)。 - PromQL:实现了函数
changes()和resets()。#112352 (valerypetrov)。 - 现在可以正确收集通过 Prometheus 远程写入端点执行的插入统计信息和查询。#112825 (JTCunning)。
- PromQL:当除数为无穷大时,取模运算现在会保留有限值。#113746 (fallintoplace)。
- 普通带引号的 PromQL 字符串中如果包含字面换行符,现在会被拒绝。#114381 (fallintoplace)。
- 在启用实验性的
make_distributed_plan和enable_cascades_optimizer时,设置过大的distributed_plan_workers_num不会再导致服务器因std::length_error而中止运行,此类节点数量现在会被拒绝并返回INVALID_SETTING_VALUE。#115398 (groeneai)。 - 为
TimeSeries表实现了 Prometheus HTTP API 的/api/v1/series端点:支持match[]序列选择器 (多个值取并集) 、可选的start/end时间范围,以及可选的limit参数。#115676 (nikitamikhaylov)。
性能提升
JOIN 与聚合性能
- 为经过 TopK 动态过滤 (
ORDER BY ... LIMIT n) 的查询启用查询条件缓存。QCC 条目按 TopK 计划参数进行分区,因此相同的查询会复用已缓存的 WHERE 过滤结果,而LIMIT、排序列或排序方向不同时则会生成新的条目。#104478 (alexey-milovidov)。 - 将 LIMIT 下推到按顺序聚合 (aggregation-in-order) 中,当 GROUP BY 键与 ORDER BY 键及表的 sorting key 一致时可提前终止,从而显著减少读取的行数。#104859 (thevar1able)。
- 默认启用
allow_aggregate_partitions_independently。当GROUP BY键与分区键相匹配时,ClickHouse 可以对每个分区独立聚合,并跳过全局合并步骤。若分区布局不利于该优化 (分区过少、分区过多或分区大小严重倾斜) ,运行时启发式规则会自动跳过该优化。#105128 (alexey-milovidov)。 - 默认启用
read_in_order_use_virtual_row。在包含大量 parts 的表上按主键顺序读取时 (例如ORDER BY primary_key LIMIT n) ,仅读取真正可能影响结果的 parts (外加一个最多包含max_threads个 parts 的预读窗口,以保持并行读取) ,从而显著降低峰值内存占用。#106215 (alexey-milovidov)。 - 降低了
JOIN的内存使用量并提升了其性能。哈希连接的右侧现在使用紧凑的、基于索引的 8 字节行引用,因此对于所有键类型,ALL连接的哈希表条目都与ANY连接一样小。在大型parallel_hash连接查询上进行了基准测试——对 1 亿至 3 亿行的表基于UInt64和String键执行INNER和ANY连接,涵盖唯一键和重复键两种情况:查询耗时中位数缩短约 12%,峰值内存占用减少约 15%,且没有任何查询变慢。其中基于UInt64键的INNER连接提升最为明显 (耗时中位数缩短约 21%,内存减少 38%) 。#107189 (harikrishnan94)。 - 新增 dpsub 连接顺序枚举算法,能够以低于 dpsize 的优化开销生成最优连接计划,并支持非内连接。#107351 (fkastrati)。
- 为聚合状态单独挂接内存跟踪器,而不再使用整个查询的内存,从而避免将内存使用量较小的单级聚合转换为两级聚合。#107490 (m-selmi)。
- 改为基于查询计划而非 AST 计算聚合哈希表大小统计信息的缓存键,从而避免在分析聚合查询时构建完整的查询 AST。#107643 (novikd)。
- 支持根据首次运行时收集的统计信息,将首次查询中使用的
hash连接在后续运行中切换为parallel_hash。#108125 (m-selmi)。 - 利用运行时连接统计信息中的哈希表大小,在后续查询执行中优化连接运行时过滤器的大小。可通过新增设置
join_runtime_filter_size_from_hash_table_stats进行控制。#108313 (m-selmi)。 - 对分区
MergeTree表上的DISTINCT查询进行优化:将每个分区的行保留在同一个 stream 中,使每个 stream 的预备DISTINCT处理互不相交的键集合,避免同一组键出现在多个预备DISTINCT中,从而提升查询速度并降低内存使用量。此优化适用于分区表达式是DISTINCT列的确定性函数的情况,并由基于分区数量和数据倾斜程度的代价启发式规则决定是否启用 (可通过设置force_distinct_partitions_independently强制开启,默认禁用) 。这种按分区不相交的特性还会经由Expression、Filter和ARRAY JOIN步骤传递给下游最终的DISTINCT、LIMIT BY和GROUP BY算子,使它们同样可以跳过合并。该功能由新增设置allow_distinct_partitions_independently(默认启用) 控制,并可通过max_number_of_partitions_for_independent_distinct调整启发式规则。#108326 (nihalzp) 。 - 现在即使
ON子句中同时包含非等值谓词,也会基于等值键构建运行时过滤器,从而在混合等值与非等值条件的连接中减少进入哈希连接的行数。LEFT ANTI JOIN不受影响。#108579 (29antonioac) 。 - 将聚合和连接所用哈希表的软件预取阈值从
4 * L2 cache size降低到L2 cache size,使哈希表一旦超出 L2 缓存容量即启用预取。此项修复了在报告 L2 容量较大的平台 (例如 L2 为 2 MiB 的 aarch64) 上,对中等规模哈希表 (约 1-8 MiB) 执行GROUP BY和JOIN时出现的性能回退。#108655 (groeneai) 。 - 提升窗口函数性能。对宽表执行且包含
SELECT *的窗口查询,现在内存使用量显著降低,运行速度也更快。使用OVER ()和OVER (ORDER BY ... RANGE ...)时,quantile*、uniq*、groupArray等窗口聚合函数的执行速度更快。cume_dist函数同样得到提速;此外,使用PARTITION BY或ORDER BY的窗口在包含大量重复值的列上性能更好。#108688 (nihalzp) 。 - 对于不含聚合函数的聚合查询,现在会使用基于
HashSet的方法代替HashMap(仅限受支持的键类型) ,实测最高可提速 1.8 倍。#108862 (nickitat) 。 - 降低
parallel_hash连接算法中锁争用带来的开销。#108938 (m-selmi) 。 - 新增
join_algorithm取值parallel_full_sorting_merge:对于哈希兼容的等值连接,它会按连接键的哈希值将 full sorting merge join 切分为多个相互独立的分片级 merge join,并在所有线程上并行执行。它在实现并行化的同时,保留了 merge join 内存占用低、流式处理的优势 (在一项基准测试中,比parallel_hash快约 2.4 倍,内存占用减少约 3.3 倍) 。ASOF连接会回退为单个full_sorting_merge;对于哈希不兼容的键类型 (浮点数、JSON、Object、Dynamic) ,仅跳过哈希分散重写,在启用query_plan_join_shard_by_pk_ranges时仍可在数据源处按主键范围分片。结果不保证有序。#109005 (alexey-milovidov) 。 - 现在,当表的当前活跃大小加上写入块的大小不超过新设置
materialize_statistics_on_insert_max_table_size(默认 25 GiB) 时,列统计信息默认会在INSERT时物化;该检查针对每个写入块分别进行,因此向空表首次批量加载数据时,仍可能为每个写入块物化统计信息。这使基于代价的连接优化器能够准确估算新加载的维度表,避免产生极差的连接顺序 (例如,TPC-H Q5 和 Q8 在 scale factor 40 下不再超时) ,而已有的大型事实表仍会在合并期间物化统计信息。#109454 (alexey-milovidov)。 - 优化了无键聚合场景下的聚合函数
uniqCombined。#109794 (CurtizJ)。 - 优化了聚合函数
uniqHLL12和uniqCombined。#109831 (CurtizJ)。 parallel_hash连接算法在另外两种情况下也能并行处理未连接的行:存在残余过滤器时,以及连接键较小 (使用单层哈希映射) 时。#110008 (m-selmi)。- 当谓词仅引用窗口的
PARTITION BY列时,将过滤器下推到窗口函数之下。此类写在窗口之后的谓词 (包裹窗口子查询的外层WHERE,或QUALIFY中的合取项) 现在可以下推到存储层,从而启用主键/分区裁剪、跳过索引和投影。例如,SELECT ... row_number() OVER (PARTITION BY key ORDER BY ts) AS rn ... QUALIFY rn = 1 AND key = 'x'不再需要读取整张表并对其执行窗口计算。#110114 (groeneai)。 - 在
join_use_nulls = 1时,若拒绝 NULL 的WHERE条件引用了外连接两侧的列 (例如WHERE l.k = 42 AND r.k = 42) ,现在会将该连接转换为INNER(或LEFT/RIGHT) 并利用主键进行裁剪,与join_use_nulls = 0时的行为一致。此前这种情况下会跳过该转换,导致两张表都被完整读取。#110121 (groeneai)。 - 优化了无键聚合中的函数
uniq、uniqExact和uniqHLL12。#110150 (CurtizJ)。 ON条件恒为假的JOIN(例如ON 1 = 2、ON NULL,或可折叠为假的条件,如a.t = 'A' AND a.t = 'B') 不再读取对结果无贡献的一侧。一项新的查询计划优化会将不可能产生任何行的输入侧替换为空数据源。该行为由设置query_plan_short_circuit_constant_false_join控制 (默认启用) 。#110234 (groeneai)。- 并行执行单层聚合哈希表的最终合并:键空间被划分为互不相交的哈希分区,由各线程独立合并 (设置
enable_parallel_single_level_merge,默认启用) 。对于每线程哈希表未达到两级阈值、但合并阶段占用了大部分运行时间的GROUP BY查询,可显著提速。#110395 (nihalzp)。 - 单个
String聚合键现在采用更紧凑的哈希表表示,从而提升以字符串为主的GROUP BY工作负载的性能。新增的enable_packed_string_keys_in_aggregation设置默认启用;禁用该设置,或将compatibility设为低于26.8的版本,将恢复使用旧版StringHashTable路径。对于长度超过 11 字节且基数极低的键,旧路径可能更快。#110573 (harikrishnan94)。#112089 (harikrishnan94)。 - 在稀疏场景下,full sorting merge join 的性能最高提升 1.5-3 倍。#111200 (vdimir)。
- 当探测端与构建端的连接键类型不同时 (例如探测键为 Nullable,而构建键为非 Nullable) ,现在也会启用
join_runtime_filter_from_fixed_hash_table。#111244 (m-selmi)。 - 当右侧包含
NULL连接键或被ON表达式过滤掉的行时,通过避免重建 null map,提升了使用parallel_hash算法的RIGHT和FULL连接的性能。#111258 (m-selmi)。 - 为并行
GROUP BY新增自适应算法 (由设置enable_adaptive_aggregator控制,默认启用) :每个线程先在各自的哈希表中进行聚合,当表中的键数达到adaptive_aggregator_freeze_threshold时将其冻结。这样,高频键会持续更新驻留在缓存中的小型表,无需任何协调;低频键则按哈希值路由到各个桶的积压队列中,并在按桶并行的合并阶段中仅聚合一次。#111459 (nihalzp)。 - 通过避免为每个值重建
ColumnDynamic,加快了对存储在共享数据中的 JSON/Object列值逐行计算哈希的速度 (例如对 JSON 列执行uniq/uniqExact,以及基于哈希的GROUP BY/DISTINCT键都会用到) 。哈希值保持不变。#111501 (valerypetrov)。 - 提升了 ON 子句中包含多个
OR析取项的 RIGHT 和 FULL 哈希 JOIN 的性能,以及带有残余 (不等) 条件的 RIGHT/FULL JOIN 的性能。#111590 (m-selmi)。 - 当哈希连接配置了自动落盘阈值 (自 26.5 起默认如此) 时,现在也可以通过 JOIN 按顺序读取。该优化生效时,连接会保留在内存中,以维持左侧的顺序;设置
query_plan_read_in_order_through_spilling_join = 0可恢复之前的行为,即此类连接不参与按顺序读取,可自由落盘。此外,对按顺序读取的LEFT JOIN执行ORDER BY ... LIMIT时,不再将整张表的行数报告为预计读取行数,因此在read_overflow_mode = 'throw'下,提前终止的读取不会再触发max_rows_to_read限制。#111973 (alexey-milovidov)。 - 在合并期间为
TTL ... GROUP BY聚合重新启用连续键优化。此前构造聚合器时,在本应传入min_hit_rate_to_use_consecutive_keys_optimization(取值范围为[0, 1]的命中率,默认 0.5) 的参数位置误传了min_chunk_bytes_for_parallel_parsing(字节阈值,默认 10 MiB) ,导致该路径上的优化一直处于禁用状态。查询结果不受影响。#112314 (groeneai)。 - 序列化查询计划时,
ARRAY JOIN的延迟列复制不再丢失。此前在serialize_query_plan = 1时,执行远程计划片段的节点会忽略enable_lazy_columns_replication,始终物化所有复制副本,尽管该设置默认处于启用状态。#112330 (groeneai)。 - 当
WHERE等值条件的操作数类型不同但存在共同超类型 (例如Int32和Nullable(Int32)) 时,现在会将其合并到JOIN条件中,从而使 CROSS 连接能够转换为 INNER 连接。#112630 (m-selmi)。 - 修复了复制元素以共享数据形式保存
JSON值的Array时出现的二次方重新分配问题,例如将常量Array(JSON)传递给聚合函数的场景。此类查询复制的字节数会随行数呈二次方增长。#112897 (groeneai)。 - 当 MergeTree 主键或分区键上范围谓词的边界值通过与单行常量侧的
JOIN ON子句提供时 (例如SELECT count() FROM t JOIN bounds ON t.d >= bounds.lo AND t.d <= bounds.hi) ,恢复了对数据分片和粒度的裁剪。自 25.2 起,此类查询会读取所有数据分片,而此前可用于恢复裁剪的query_plan_use_logical_join_step设置已在 26.5 中废弃,导致裁剪再也无法恢复。#112957 (groeneai)。 - 修复了对基于大量不同结构表的
Merge表执行 JOIN 时,查询规划呈三次方复杂度的问题。此前此类查询可能在查询规划阶段耗费数分钟,且不响应max_execution_time或KILL QUERY。#113140 (alexey-milovidov)。 - 修复了一个性能回退问题:不带
GROUP BY键的聚合在每次执行时都会序列化完整的输入计划子树 (包括常量折叠字面量的全部内容) ,只为计算一个根本用不上的哈希表大小缓存键。例如SELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000))))这样的查询,此前每次执行在查询计划优化上约耗时 63 ms,现在仅需 0.15 ms。#113333 (groeneai)。 - PromQL 聚合运算符
topk、bottomk和limitk现采用流式计划求值,其选择状态为O(time_steps * k),不再将所有序列收集到单行中并占用O(time_steps * series^2)的中间内存。此前在高基数指标上因MEMORY_LIMIT_EXCEEDED而失败的查询,现在可在有界内存中运行,且求值过程由单线程改为并行执行。#113656 (nikitamikhaylov)。 - 将
timeSeries*ToGrid聚合函数内部按桶划分的哈希表替换为扁平的有序样本数组:对于有序输入 (绝大多数情况) ,样本写入变为 O(1) 的追加操作,同时省去了最终化阶段按桶进行的复制与排序。#113681 (nikitamikhaylov)。 - 被多个计划步骤共享的 PromQL 子表达式 (
topk/bottomk/limitk的操作数、or的左侧) 现在只求值一次而非两次:由 PromQL 生成的 SQL 会物化共享子查询。这消除了对样本表的重复扫描;基于rate的topk冷查询速度提升约 2 倍,kubernetes-mixin 规则查询性能提升 10–29%。#113772 (nikitamikhaylov)。 - 对于使用
ORDER BY <column> LIMIT n(TopK) 优化的查询,查询条件缓存现已默认启用。如需禁用,可设置use_query_condition_cache_for_top_k = 0。#111492 #114539 (alexey-milovidov) 。 - 在合并之前,并行执行每线程聚合状态从单级到两级的转换。此改动修复了在核心数非常多的机器上,带有重型聚合状态 (例如
COUNT(DISTINCT ...)、ClickBench Q10/Q11) 的短GROUP BY查询出现的 2-3 倍性能回退;该回退是在 26.7 开发构建版本中为使聚合内存统计更精确而引入的。#114691 (alexey-milovidov) 。 - 加速分区
MergeTree表上的窗口函数:每个分区通过各自独立的 stream 读取,并按分区计算窗口,从而省去通常在窗口排序前将所有行在线程间重新打散的哈希分发步骤。该优化适用于表的分区表达式是窗口PARTITION BY列的确定性函数的情况,并与按分区执行的GROUP BY/DISTINCT采用相同的成本启发式规则 (相对于max_threads有足够多的分区,且不存在占主导地位的分区) 。由新设置allow_window_partitions_independently(默认启用) 、force_window_partitions_independently和max_number_of_partitions_for_independent_window控制。#114783 (nihalzp) 。 - 加速
timeSeries*ToGrid聚合函数:每个样本的桶计算不再使用 Int128 除法,且落在同一个桶中的连续样本会跳过哈希表查找。#114889 (nikitamikhaylov) 。 timeSeries*ToGrid聚合函数现在将落入同一网格桶的连续样本作为一批进行处理,使timeSeriesRateToGrid及相关函数在已排序时间序列数据上的样本摄取阶段提速 1.2-2 倍。#115041 (nikitamikhaylov) 。- 不带
GROUP BY键的聚合不再将其单行输出扩散到max_threads个流,因此对于执行计划在此类聚合之后仍有后续步骤的查询,其流水线会显著缩小 (需要创建、调度和分析的处理器更少) ,且不会损失任何并行度。#115170 (nikitamikhaylov) 。 - 加快 PromQL 即时查询的计算:
timeSeries*ToGrid聚合函数对单点网格采用向量化的样本分类路径,timeSeriesIdToGroup则直接填充其结果列。#115267 (nikitamikhaylov) 。 - 当
JOIN的ON子句包含多个以OR连接的等值条件时,不再物化查询中未选取的右侧键列。#115465 (nickitat) 。 - 当右侧存在大量重复的连接键时,加快
ANY、SEMI或ANTI连接的哈希表构建:连接不再针对右侧的每一行从内存中重新读取join_any_take_last_row设置。#115820 (nickitat) 。 - 加速基于
String、FixedString和LowCardinality键且不含聚合函数的GROUP BY:查询不再为每一行向哈希表重写未使用的占位符,而仅对新增键的行执行此操作。#115834 (nickitat) 。 - 降低了对大型常量折叠字面量执行带键聚合时的内存使用量和查询计划优化时间。聚合哈希表统计信息的缓存键现在会在序列化的同时完成哈希计算,不再先在内存中累积,因此携带大型字面量的查询计划在优化期间不再保留该字面量的副本。以 80 MB 的字面量为例,峰值内存占用降低约 250 MB,优化速度提升约 2.5 倍。计算得到的键保持不变。#115847 (groeneai)。
- 优化了
GROUP BY ... ORDER BY ... LIMIT和GROUP BY ... LIMIT查询:在聚合过程中维护一个有界堆,提前剪除不可能出现在结果中的分组,从而显著降低高基数分组场景下的内存使用量和执行时间。该优化由enable_group_by_top_k_optimization设置控制。基于 Dmitriy Terenichev 的初始实现。#96630 (thevar1able)。
查询优化与执行
- 使用并行副本进行按序读取时,现在采用与本地读取相同的逻辑,将表拆分为
max_threads个部分,以提升并行度。#101434 (nickitat)。 - 为 Parquet 读取器新增行组级和页级的 GeoParquet 空间裁剪。行组裁剪会跳过边界框与查询几何体不重叠的整个行组;页级裁剪则利用
covering.bbox列索引跳过行组内的无关页。此外,还通过IFunctionBase::isSpatialPredicate()泛化了空间谓词下推,并新增GeoFilter,用于在读取 Parquet 行时对空间谓词进行求值。#104435 (bacek)。 - 新增
use_constant_folding_in_index_analysis设置 (默认禁用) 。启用后,MergeTree主键、MinMax和跳数索引分析会针对每个数据分片,分别将分区级常量折叠到过滤谓词中,从而改善分支依赖于分区值的过滤条件的裁剪效果,例如在PARTITION BY a下的(a = 1 AND b >= 1) OR (a = 2 AND b > 10)。#104582 (Michicosun)。 - 对于启用
vector_search_with_rescoring的向量搜索查询,在查询管道中执行精确距离计算之前,先进行精确的行定位。#105591 (skuznetsov)。 - 新增一项查询计划优化:将可缩减数据量的函数 (
length、lengthUTF8、empty、notEmpty) 下推到Sorting和Filter步骤之下,用定长结果替换较宽的String/FixedString参数,从而既无需在排序时缓冲,也无需在过滤时复制。该优化由新设置query_plan_push_down_volume_reducing_functions控制,默认启用。#106199 (fastio)。 - 将每个缓存文件的大小编码到文件名中 (
<offset>_<size>) ,无需再对每个文件执行stat,从而加快启动时文件系统缓存的加载速度。旧版本写入的缓存文件仍可正常加载。#107415 (alexey-milovidov)。 - 提升了带主键过滤条件的文本搜索查询的性能。#108114 (CurtizJ)。
- 提升了
pointInPolygon函数在多边形为常量时的性能。预处理多边形缓存现在以原始常量参数作为键,因此常量多边形只需解析一次 (缓存未命中时) ,而无需针对每个输入块重复解析。#108184 (groeneai)。 - 当该功能处于禁用状态时 (
predicate_statistics_sample_rate = 0,即默认值) ,不再在 MergeTree 读取路径上维护system.predicate_statistics_log选择性计数器。这样每次读取都省去了逐颗粒的原子更新以及O(rows)的过滤器 popcount 操作,修复了在 aarch64 上尤为明显的性能回退。#108190 (groeneai)。 - 新增
merge_use_batch_sorting_queueMergeTree设置,可选择为普通MergeTree合并启用批量排序队列,对于排序合并开销较大的合并负载,可降低 CPU 时间和实际耗时。#108468 (rorylshanks)。 - 构建 actions DAG 时不再重复构建共享子表达式,从而加快分析器的查询规划速度,适用于多次引用同一
WITH别名或多次重复同一子表达式的表达式 (例如深度嵌套的if/multiIf链) 。#108523 (novikd)。 - 加快了包含大量或超长
AND比较链的查询的查询分析速度:optimize_and_compare_chain优化现在受工作量预算约束 (新增设置optimize_and_compare_chain_max_hash_work) ,不再对查询树的大部分内容进行哈希计算;此外,lambda 解析在其递归保护中不再重复计算 lambda 主体的哈希。#108757 (alexey-milovidov)。 - 仅用于过滤的后处理器 (
if(..., '', token)) 现在直接基于原始标记构建 granule,并在构建时丢弃空值,从而避免了通用路径中针对每次出现的物化操作以及ActionsDAG执行。#109049 (ahmadov)。 - 消除了分布式查询计划中
ShuffleSendStep的单线程瓶颈:每个上游流现在各自独立地按目标桶分发其行,而不再将整个片段汇集到单个ScatterByPartitionTransform中处理。#109206 (davenger)。 - 降低了列数很多的查询在表达式求值时的 CPU 开销 (例如,在步长较小的
QBit列上执行向量搜索时,每个向量会展开为数百个位平面子列,并全部传入同一个*DistanceTransposed调用) 。#109380 (alexey-milovidov)。 - 当谓词仅引用
LIMIT BY键列,且该子句对每个非空分组至少保留一行 (LIMIT n BY且n >= 1、OFFSET 0) 时,将过滤器下推到LIMIT BY之下。这样,此类谓词 (以外层WHERE包裹LIMIT BY子查询的形式编写) 即可下推至存储层,用于主键裁剪、跳过索引和投影,而无需先读取整张表再执行每组 top-N,同时不会改变OFFSET、LIMIT 0 BY或负数LIMIT BY形式的异常语义。#110116 (groeneai)。 - 在主键索引分析中避免了每次超矩形检查时的堆内存分配,视查询形态不同,mark 过滤速度可提升 5-26%。#110153 (raimannma)。
- Parquet 过滤器下推 (行组裁剪和列索引) 现在支持
DateTime64各变体之间、Decimal各变体之间以及Float32/Float64之间的转换。#110457 (al13n321)。 - 优化了使用 sparseGrams 分词器构建基于文本和布隆过滤器的跳过索引的过程 #110541 (UnamedRus)。
- 在 PREWHERE 条件排序中综合考虑 I/O 开销与选择性。此改动修复了自 https://github.com/ClickHouse/ClickHouse/pull/101275 起在某些情况下出现的 PREWHERE 执行性能回退问题。属于 https://github.com/ClickHouse/ClickHouse/issues/110462 的一部分 #110695 (Avogar)。
- 减少了对后处理器
IN/NOT IN过滤器中所定义标记的哈希计算。#111690 (ahmadov)。 - 启用 enable_lazy_columns_replication 时,使用非常量模式的 mapContainsKeyLike、mapContainsValueLike、mapExtractKeyLike 和 mapExtractValueLike 函数占用的内存更少、耗时更短。模式不再在捕获时为每个 map 条目立即复制,而是推迟到内部 lambda 执行时才复制,并能更早释放,因此峰值时模式的展开副本会少一份。#111749 (diegomestre2)。
- 默认启用两项磁盘端特性 (并提升为 beta) :1)
packed_skip_index_max_bytes = '1M':不超过 1 MiB 的跳数索引子流现在会写入每个 part 中的单个skp_idx.packed归档文件,从而减少对象存储上的对象数量和写入请求。兼容性:仅影响新写入的 parts,且这些 parts 在旧版本上仍可完整读取;26.6 之前的版本只是不会利用打包索引进行剪枝 (将其视为未 materialized) 。设置packed_skip_index_max_bytes = 0可保留每个文件独立存放的布局。2)compute_exact_num_defaults_for_sparse_columns与optimize_trivial_count_with_sparsity_filter:持久化每列精确的num_defaults计数器;当谓词将行划分为默认值与非默认值时,可直接据此得出SELECT count() FROM t WHERE <pred>的结果,无需扫描数据。兼容性:旧版本会忽略serialization.json中的exact_num_defaults标志,因此降级后 parts 仍可完整读取;count 重写仅适用于带有精确计数器的 parts,因此在混合新旧 parts 的表上结果依然正确。#111816 (Algunenano)。 - 传递条件优化在无法应用完整过滤器时,现在仅将其附加过滤器用于索引分析。参见
optimize_and_compare_chain设置。#112076 (yariks5s)。 - 实验性 TimeSeries 引擎的 Prometheus 查询 API (
/api/v1/query、/api/v1/query_range) 现在改为并行执行查询,不再局限于单线程。#112108 (nikitamikhaylov)。 - 对常量向量调用
randomHadamardTransform时,现在只计算一次,而不再逐行计算。对于先用randomHadamardTransform旋转查询向量、再与QBit列进行比较的向量搜索查询,这将带来明显提速。#112921 (alexey-milovidov)。 - 恢复了在主键列上按
IN (subquery)过滤的单个变更中,各 part 任务之间的 set 共享。enable_sharing_sets_for_mutations默认开启,但为主键分析构建的 set 此前不再参与共享缓存,导致包含 N 个 parts 的表会将同一个 set 物化 N 次。#112941 (groeneai)。 - 在分布式查询计划 (
make_distributed_plan) 中,ORDER BY ... LIMIT k现在会在每个副本上使用延迟物化:宽列仅针对该副本本地的 top-k 行读取,而不必为每个候选行读取。#113111 (shankar-iyer)。 - 加快使用
uniq_v2列统计信息时的查询计划速度。估算的不同值数量现在会被缓存,不再在每次请求时重新计算,而查询计划在单个查询中会多次发出此类请求。#113357 (groeneai)。 - 过滤器下推现已支持 Parquet 和 ORC 文件中的
Tuple子列。对file()、s3()或url()使用诸如WHERE tup.1 = 555555的谓词时,现在会利用该元组元素自身的统计信息来剪枝行组和行索引步长,而无需读取整个文件。#113383 (groeneai)。 - 提升基于 TimeSeries 引擎的 PromQL 查询性能:内部选择器 SQL 现在直接读取样本表的主键列 (不再进行无实际作用的类型转换) ,并先检查时间戳范围、再检查 series-id 集合,使冷查询中大量使用选择器的查询提速 30-44%。#113768 (nikitamikhaylov)。
- 当 id 布局为使用规范 id 生成器的二元组时,匹配某一指标所有序列的 PromQL 选择器现在会在索引分析阶段,通过
id上的连续主键范围来过滤TimeSeries表的样本表,而不再使用庞大的id IN <set>条件。这消除了大量使用选择器的 PromQL 查询中占主导地位的单线程索引分析开销:在一张包含 620 亿个样本的表上,仪表板和规则类查询的冷启动延迟最多降低 45%,整个测试套件的冷启动几何平均值降低 11%。#114131 (nikitamikhaylov)。 - Prometheus HTTP API 端点
/api/v1/query和/api/v1/query_range现在对多个计划步骤共享的 PromQL 子查询只求值一次,与prometheusQuery和prometheusQueryRange表函数的现有行为保持一致。此前,以enable_analyzer = 0发起的请求,或由配置文件中设置了该项的用户发起的请求,会针对每个引用该子查询的步骤重新扫描一次共享子查询。#114261 (groeneai)。 - 修复了 26.7 中的一个回归问题:对于按
DateTime64列的toUnixTimestamp(或其他整数转换) 排序的MergeTree表,针对该列的普通范围过滤不再使用主键,而是会读取匹配分片中的所有粒度。此外,对于按原始DateTime64列排序的表,诸如toInt64(ts) >= c的过滤条件现在也会使用主键。#114413 (alexey-milovidov)。 - 对于聚簇列 (例如按主键排序的列) ,遇到值相等的连续行时会复用上一行的结果,从而加快
IN的执行速度。#114853 (nikitamikhaylov)。 - 修复了函数
h3kRing、h3ToChildren、h3PolygonToCells和h3PolygonToCellsWithContainment在基于大量行构建结果时时间复杂度呈二次方增长的问题。在一次 CI 压力测试中,一个处理 196 000 行的查询耗费了 838 秒用于内存复制;现在仅需约 5 秒。#115773 (groeneai)。 - 优化了反向字典查找。诸如
WHERE dictGet(dict, attr, key_expr) = value的常量等值谓词现在会直接常量折叠为键过滤器 (key_expr = const、key_expr IN [...]或WHERE 0) ,而不再改写为IN (SELECT ... FROM dictionary(...))子查询;同时,dictGetKeys的常量路径现已支持并行执行。#91164 (nihalzp)。 - 新增设置
merge_tree_generic_exclusion_search_max_steps,用于限制通用排除搜索算法分析每个数据分片的主键索引时所用的步数。该预算会优先分配给剩余的最大键范围,因此即使预算很小,也能裁剪掉大部分数据;未完全分析的范围会被整体读取,因此查询结果依然正确,只是可能会读取更多粒度。该限制并不严格:最多可超出merge_tree_coarse_index_granularity步,此外分片中已划分出的每个范围 (例如由查询条件缓存划分) 还会各额外增加一步。默认值 0 表示不限制步数。#92779 (EmeraldShift)。 - 对基于分布式表的
VIEW执行带有ORDER BY和LIMIT的查询时,现在会使用“合并已排序流”优化。外层的ORDER BY/LIMIT会被下推到简单视图的内部查询中,由各分片在本地完成排序,再由协调节点合并这些预先排好序的流,而无需在协调节点上执行完整排序。#94102 (matanper)。
存储、I/O 与数据湖性能
- 对于
MergeTree表,当某个主键列同时也是分区键的输入列时,在主键分析过程中利用分区 minmax 索引的边界裁剪更多粒度。例如,在使用ORDER BY (id, event_time)和PARTITION BY toYYYYMM(event_time)的MergeTree表中,ClickHouse 会在主键索引分析期间使用event_time上的分区 minmax 索引,从而做出更精准的粒度裁剪决策。该行为由新增设置use_partition_minmax_for_primary_key_pruning控制 (默认启用) 。#103480 (UnamedRus)。 - 加速在已排序数据流中扫描相等键值连续序列的算子,包括按序
DISTINCT、按序LIMIT BY、按序负向LIMIT BY,以及full_sorting_merge和partial_merge连接。#106502 (nihalzp)。 - 当列块完全采用字典编码时,Parquet v3 读取器现在可以针对等值条件和
IN条件,利用字典页跳过整个行组 (作为 min/max 统计信息和布隆过滤器之外的补充手段) 。该行为由新增设置input_format_parquet_dictionary_filter_push_down控制。#106952 (alexey-milovidov)。 - 改用 libdeflate 进行 gzip/zlib/deflate 压缩和解压缩,提升了
.gz/HTTP/url/s3数据以及 Parquet GZIP 编解码器的处理速度 (压缩约快 1.15 倍且压缩比更高,解压缩约快 1.4–1.5 倍) 。#108074 (alexey-milovidov)。 - 加速默认去除空白字符的
trimLeft/trimRight/trimBoth函数 (及其别名ltrim/rtrim/trim) :无需去除空白的连续行会一次性批量复制,逐行空格扫描仅对确实带有前导或尾随空格的行执行。#108177 (groeneai)。 - 在解析当前 manifest 文件的同时预取下一个 manifest 文件,使 I/O 与 CPU 计算并行进行,从而加快 Iceberg 表的读取速度。#108543 (asya-ch)。
- 使用重评分的向量搜索查询现在仅对向量索引返回的候选行计算精确距离,而不再对同一
MergeTree粒度中的相邻行进行暴力重评分。#108846 (skuznetsov)。 - 新增
merge_tree_min_bytes_per_read_stream设置,用于在高核心数服务器上执行普通的本地无序窄列MergeTree扫描时,减少过多的读取流及流水线开销。#109035 (jiebinn)。 - 加速共享数据中包含大量稀疏路径的
JSON列的序列化与合并。在将共享数据展平为按路径划分的列时,flattenAndBucketSharedDataPaths不再针对每一行扫描所有已累积的路径列,也不再逐个单元格插入默认值;针对所有路径的逐行扫描已被移除,空缺部分改为批量回填。#109341 (groeneai)。 - 当通信双方的协议修订版本均为 54489 或更高时,原生协议现在会先发送一个独立的累积字节偏移量 stream (与
Array存储偏移量所用的布局相同) ,再发送拼接后的数据,以此传输String列,而不再为每个值附加 varint 长度前缀。这样,客户端读取String列时即可精确预分配缓冲区,并通过单次批量复制完成读取,速度约为逐值布局的 4 倍。旧版客户端和服务器不受影响:该布局通过协议修订版本协商确定。Native和Buffers格式也可通过新增设置output_format_native_write_string_with_size_stream/input_format_native_read_string_with_size_stream使用相同布局 (默认关闭,以保持格式的可移植性) 。#110320 (vahid-sohrabloo)。 - 对于按主键顺序读取 (
ORDER BY为 sorting key 的前缀) 且LIMIT较小的FINAL查询,不再使用split_intersecting_parts_ranges_into_layers_final。#110431 (KochetovNicolai)。 - 从对象存储 (包括 Iceberg 表) 读取 Parquet 文件时支持延迟物化 (late materialization) :对于
ORDER BY ... LIMIT n查询,排序和过滤用不到的列仅针对经LIMIT筛选后保留的n行进行读取。以 S3 上一个 200 MB 的 Parquet 文件为例,SELECT k, s ... ORDER BY k DESC LIMIT 10仅读取 3.3 MB,而非 171 MB (IO 减少至 1/51,速度提升 8 倍) 。该功能由新增设置query_plan_optimize_lazy_materialization_for_object_storage控制 (默认启用,且需同时启用query_plan_optimize_lazy_materialization) 。#110970 (alexey-milovidov)。 - 对包含大量删除文件的 Iceberg 表执行查询时,启动速度更快。ClickHouse 现在会并发读取和解码删除清单文件,而非逐个处理,使各文件的存储读取得以并行进行。新增设置
iceberg_delete_manifest_decode_concurrency(默认值为4) 用于控制同时解码的文件数量。#112679 (asya-ch)。 - 新增可选功能:将 UInt128/UInt256/Int128/Int256 以 DECIMAL 形式序列化到 Parquet,从而支持行组级和页级剪枝。#113347 (bobrik)。
- 修复了读取器链中的某个步骤读取碎片化标记范围 (例如经主键或跳数索引过滤后的范围) 时,远程磁盘上读取请求成倍增加的问题。#113584 (CurtizJ)。
- 写入 sorting key 全部为常量的
MergeTree数据部分时,跳过多余的有序性检查扫描。#113899 (perfloop-agent)。 ORDER BY ... LIMIT n查询的延迟物化现在也适用于通过file表函数和File表引擎读取的本地 Parquet 文件:排序和过滤用不到的列仅针对经LIMIT筛选后保留的n行进行读取。如果文件在两轮读取之间被修改,对保留文件的第二次读取将以安全方式失败,并报出新增的FILE_CHANGED_DURING_READ错误。该功能由新增设置query_plan_optimize_lazy_materialization_for_file控制 (默认启用) 。此外,还修复了所请求的子列 (例如JSON列的子列) 被延迟读取时,对象存储的延迟物化报错Not found column or subcolumn ... in block的问题。#114262 (alexey-milovidov)。- 加速分区
MergeTree表上IN (subquery)的 Set 构建:将每个分区的行保留在单个 stream 中,并在各 stream 内独立去重,这样,唯一的 Set 填充转换 (此前需串行地对每一行计算哈希) 只需处理去重后的行。当分区表达式是子查询输出列的确定性函数时,此优化生效。若最大分区的行数超过平均分区行数的两倍,则不应用该优化;新增设置force_creating_set_partitions_independently(默认禁用) 可跳过此检查。该优化由新增设置allow_creating_set_partitions_independently(默认启用) 控制。#114645 (nihalzp)。 - 将已轮转且未配置生存时间 (TTL) 的非复制
MergeTree系统日志表标记为table_readonly,以避免不必要的后台操作。table_readonlyMergeTree设置现在还会禁止普通MergeTree表上的所有后台工作 (包括常规合并、生存时间 (TTL) (DELETE/MOVE/重新压缩) 合并和重新压缩合并、后台变更以及后台分片移动) ,并拒绝会修改数据的分区命令 (ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITION,以及以该表为目标的MOVE PARTITION ... TO TABLE) ;此前已拒绝的插入、变更和OPTIMIZE也仍会被拒绝。因此,在该设置启用期间,配置了生存时间 (TTL) 的table_readonly表将不再清理其过期数据。#95079 (matt-metivier)。
内存与资源效率
- 降低
UNLOCK SNAPSHOT的内存使用量:不再加载解锁路径用不到的各数据 part 元数据,避免快照包含海量 parts 时出现内存不足。#111849 (jkartseva)。 - 减少读取备份元数据时的内存分配:现在每个文件条目都以移动而非复制的方式存入内存映射。#111718 (jkartseva)。
函数、类型与格式性能
- 将
Decimal值格式化为文本的速度大幅提升——对于 scale 较大的Decimal256,最高可提升 190 倍;对于Decimal64,约提升 1.6 倍。在支持 AVX-512 IFMA 的处理器上,将 64 位整数转换为文本的速度提升约 1.4 倍。同时修复了toDecimalString的舍入问题:此前该函数会丢失小数部分产生的进位,toDecimalString(toDecimal64('9.995', 3), 2)原先返回9.00,现在正确返回10.00。#112457 (thevar1able)。 - 提升了
partial_merge连接算法在FixedString键上的性能:改为批量比较一段连续的值,而不再对每个值单独调用一次比较。#105737 (4ertus2)。 HashJoin现已原生支持单列、非 Nullable 的 LowCardinality 字符串键。#107264 (nickitat)。- 提升了
replaceAll和replaceRegexpAll在模式和替换内容均为单个字符时的性能 (例如replaceRegexpAll(s, ' ', '_')) 。此类替换不会改变字符串布局,因此现在只需复制一次列,并就地改写匹配的字节,而不再针对每次匹配执行搜索循环。#108178 (groeneai)。 - 加快了在 best-effort 模式 (
date_time_input_format = 'best_effort'、cast_string_to_date_time_mode = 'best_effort',即默认设置) 下解析规范YYYY-MM-DD hh:mm:ss日期时间格式的速度,从而消除了这些默认值从basic切换为best_effort时引入的解析性能回退。#108187 (groeneai)。 - 深度嵌套的 array 和 tuple 字面量的解析时间复杂度由平方级降为线性。#108892 (alexey-milovidov)。
- 对于
SECOND、MINUTE和HOUR时间间隔,函数toStartOfInterval(别名time_bucket、date_bin) 的速度最高提升 5 倍。#109729 (raimannma)。 - 不带 lambda 调用时,函数
arraySort和arrayReverseSort处理数值数组 (包括Decimal和DateTime64) 的速度提升数倍。#109832 (raimannma)。 - 通过采用算术快速路径,加快了
addDays、addWeeks、subtractDays和subtractWeeks在固定偏移时区 (如 UTC) 下处理DateTime和DateTime64值的速度。#109836 (raimannma)。 - 对
Delta编解码器的解压缩进行了向量化。对于 8/16/32 位数据类型,解码速度提升 1.5–5 倍,扫描Delta压缩列的速度最高可提升 20%。#110189 (raimannma)。 - 加快了字符串搜索函数 (
like、position、match、countSubstrings、hasToken等) 使用常量 needle 搜索Enum列的速度:仅在去重后的枚举名称中搜索,再将结果逐行映射回去,而不再逐行搜索。#110325 (alexey-milovidov)。 - 在 needle 为非常量的情况下,将子串搜索函数 (
position、countSubstrings、multiSearch*、replaceAll/replaceOne,以及它们的不区分大小写变体和 UTF-8 变体) 的性能最高提升至 1.5 倍。具体做法是在逐行处理路径上改用基于 SIMD 的字符串搜索器,不再回退到朴素实现。#110580 (Algunenano)。 - 提升了对包含大量动态 Variant 或 JSON 路径的
Dynamic和Object列进行块压缩合并 (squashing) 与合并 (merging) 的性能。#110583 (cv4g)。 - 提升了使用
NONE编解码器时estimateCompressionRatio的执行速度 #111107 (rienath)。 - 对于路径存储在共享数据中的
JSON列,加快了排序及其他基于比较的操作。此前,每次比较值时都会物化一个临时Dynamic列,并对比较双方执行完整的二进制反序列化,导致对此类列执行ORDER BY慢得异常。#111894 (groeneai)。 - 256 位整数 (
Int256、UInt256和Decimal256) 的除法现在以 64 位 limb 为单位逐段计算商:当除数可用 64 位表示时,使用 128 / 64 除法循环,否则使用 Knuth 的 Algorithm D,不再采用逐比特移位相减的长除法。此改动影响intDiv、modulo、Decimal256算术运算,以及这些类型到文本的转换。#112477 (thevar1able)。 - 从二进制编码的类型 (
Native,或启用了input_format_binary_decode_types_in_binary_format的RowBinary) 中读取Nested列时,不再先将类型转换回类型名称再重新解析。此外,格式错误的嵌套Tuple类型名称现在会直接报告为语法错误,而不会再耗费随嵌套深度呈指数增长的时间,最终以TOO_SLOW_PARSING失败。#112560 (alexey-milovidov)。 - 加快了针对 TimeSeries 表的 PromQL 查询:当连续多行的 series id 相同时,
timeSeriesIdToGroup现在会复用上一行的分组,从而省去逐行的 id 序列化和哈希查找。#113580 (nikitamikhaylov)。
其他性能提升
- 为
Arrow和ArrowStream格式实现了不依赖 Apache Arrow 库的原生读取器和写入器,避免了额外的数据复制和转换。该实现现已设为默认 (对应设置input_format_arrow_use_native_reader和output_format_arrow_use_native_writer) ,读写速度均有提升。#106522 (alexey-milovidov)。 - 优化
nullIf(key, sentinel) = const谓词,使其能够构建键范围,从而支持主键、分区和跳过索引裁剪。#107308 (adityaksolves)。 - 将 `INTERSECT ALL` 和 `EXCEPT ALL` (`INTERSECT` 和 `EXCEPT` 的默认模式) 的性能提升了数倍:现在直接以行值作为多重集的键,不再使用 SipHash 对每一行计算哈希。#107649 (Algunenano)。
- 借助 LLVM 将简单正则表达式编译为原生代码,加速了
match、extract、extractAll、replaceRegexpOne和replaceRegexpAll函数。该功能由新增设置compile_regular_expressions控制 (默认启用) ;超出支持范围的模式会透明地回退到 RE2 引擎。#108004 (alexey-milovidov)。 - 利用 NEON 对短偏移重叠复制进行向量化,加快了 AArch64 (ARM) 上匹配偏移较小的列 (例如定宽整数列) 的 ZSTD 解压缩速度。例如,在 AWS Graviton 4 上,
UInt64列的解压缩速度最高可提升约 2.3 倍。#108049 (alexey-milovidov)。 - 提升了定长、低基数列的 LZ4 解压缩速度。#108175 (nickitat)。
- 通过在分块 Myers 代码路径中避免逐行堆内存分配,提升了 ARM 上
levenshteinDistance(及editDistance) 处理中等长度字符串的性能。#108185 (groeneai)。 - 加快了在
precise_float_parsing = 1时从文本解析浮点数的速度,在几乎所有输入上都不慢于默认解析器,甚至更快。同时将内置的fast_float库升级至 v8.2.10。#108205 (Algunenano)。 - Base64 编码和解码函数现已改用
simdutf,性能得到提升。#108333 (thevar1able)。 - 针对计算开销较大的高基数键优化了
DISTINCT。#108366 (nihalzp)。 - 通过启用不保留
errno的编译器优化,提升了数学函数的性能。#108628 (nickitat)。 - 对于
T64编码的列,改为通过解析计算得出压缩后大小,而非实际执行压缩,从而加快了estimateCompressionRatio的速度。#109054 (rienath)。 - JOIN 现在可以利用左表的主键索引或跳过索引来裁剪数据颗粒。#109085 (shankar-iyer)。
- 提升 H3 地理函数 (
h3ToGeoBoundary、h3ToGeo、h3CellAreaM2/h3CellAreaRads2、geoToH3) 的性能:成对的正弦/余弦值改为一次性同时计算,并消除了坐标变换中冗余的三角函数调用。计算结果保持不变 (逐比特完全一致) 。#109399 (alexey-milovidov)。 - 将比较和符号扩展代码改为无分支实现,使宽整数类型 (
Int128、UInt128、Int256、UInt256以及基于它们的类型,如Decimal128) 的比较运算 (<、>、<=、>=) 性能最高提升 7 倍,有符号整数转换为Int256的性能也最高提升 7 倍 (针对正负混合数据) 。#109474 (raimannma)。 - 对于只有单个非常量
Nullable参数的函数,其结果现在直接共享该参数的空值映射,不再分配并合并新的空值映射。#110151 (raimannma)。 - 改用向量化归约替代逐元素比较循环,使函数
arrayMin和arrayMax在数值数组上的性能提升约 1.3-1.5 倍。#110163 (raimannma)。 - 当输入流已按 distinct 列的前缀排序时 (例如
SELECT DISTINCT a, b FROM table ORDER BY a) ,提升DISTINCT的性能。此类查询最高可提速 2.4 倍。#110170 (nihalzp)。 - 为
groupBitOr/groupBitAnd/groupBitXor以及方差函数家族 (varPop、varSamp、stddevPop、stddevSamp、skewPop、skewSamp、kurtPop、kurtSamp、covarPop、covarSamp、corr) 实现了向量化批处理路径:在条件不可预测时,配合-If组合器使用最高可提速 4 倍;方差函数家族在不使用该组合器时最高可提速 3 倍。#110461 (raimannma)。 - 优化了文本索引的分析过程。#110530 (CurtizJ)。
- 将十六进制字符的校验与转换从两次遍历合并为一次,加快了从文本解析
UUID值的速度 (例如使用JSONExtract提取为LowCardinality(UUID)、toUUID、CAST AS UUID) 。#110625 (groeneai)。 - 借助 SSSE3
pshufb对短偏移量的重叠拷贝进行向量化,加快了 x86_64 平台上匹配偏移量较小的列 (例如定宽整数列) 的 ZSTD 解压缩速度 (相当于 #108049 中 AArch64 NEON 优化在 x86_64 上的对应实现) 。#110909 (thevar1able)。 - 改用 CRC32 哈希 (与
uniqExact相同) 并内联逐行插入操作,使数值类型的groupUniqArray最高提速 3 倍。#110917 (raimannma)。 - 提升浮点列的 minmax 及基础列统计信息的效率。#111221 (cv4g)。
- 现在可直接根据文本索引的基数元数据返回
COUNT()查询的结果。#111494 (ahmadov)。 - 提升了
min和max在 128 位和 256 位类型 (Int128、UInt128、Int256、UInt256、Decimal128、Decimal256) 上的执行速度。宽整数类型最高提速 1.8 倍,宽十进制类型最高提速 3.4 倍。#111965 (raimannma)。 - 修复了
system.query_log写入过程中的性能回退问题。此前构建Settings和asynchronous_read_counters这两个 Map 列的速度比原来慢约 6 倍,在记录大量查询且每个查询都更改了许多设置的服务器上,可能导致SYSTEM FLUSH LOGS query_log超出 180 秒的超时时间。#112210 (groeneai)。 - 新增可选功能,用于缓存文本索引中不存在的词元。#112742 (rorylshanks)。
- 异步日志现在使用有界无锁队列:写入日志消息的线程不会再因互斥锁而阻塞,也不会唤醒日志线程。#112803 (alexey-milovidov)。
- 当 point 参数是类型为
Point(或其他由两个数值元素组成的Tuple) 的完整键列时,pointInPolygon现在会使用主键索引,例如对按coord排序的表执行pointInPolygon(coord, [...])。此前仅会分析使用两个标量键列的pointInPolygon((x, y), [...])形式。#112956 (alexey-milovidov)。 text_index_posting_list_apply_mode的默认值现为lazy。因此,对于设置了posting_list_codec的文本索引,文本索引查询会借助游标以打包块粒度按需解码倒排列表,而不再预先将其物化为位图。#113521 (CurtizJ)。- 当标签组 ID 位于紧凑范围内时,改用直接索引替代基于哈希的重映射,从而加快向量化 TimeSeries 标签转换。#114244 (fallintoplace)。
- 提升了文本索引合并的性能。#114525 (CurtizJ)。
- PromQL 集合运算符现使用紧凑的存在掩码。#115224 (fallintoplace)。
- 挂载系统表时,不再仅为设置表注释而将每个表的元数据 (包括完整的列描述) 复制两次。#115490 (thevar1able)。
- 加快了针对全零 PromQL 条件向量的重复序列检查。#115822 (fallintoplace)。
- 加快了
toUTCTimestamp/to_utc_timestamp和fromUTCTimestamp/from_utc_timestamp处理DateTime64参数的速度,使其吞吐量恢复到此前溢出修正后的水平。结果保持不变。#115838 (groeneai)。 - 降低了 x86-64 平台上随机数据生成 (
rand、rand64、randomString、randomFixedString、generateUUIDv4、generateUUIDv7) 的固定初始化开销。块较小时效果尤为明显;生成的值不受影响。#116158 (Algunenano)。 - 现在可以通过
enable_function_early_short_circuit设置,在分析阶段对内置的and和or启用提前短路折叠。这样可以跳过执行无效的单行count()标量子查询,同时保留常规的类型推断和语义校验。#83505 (fhw12345)。 - 对可平凡序列化的向量改为使用单次缓冲区 IO 调用 #89842 (Ergus)。
- 默认启用
optimize_or_like_chain。#94517 (alexey-milovidov)。 - 在服务器用户数量较多时,提升了从 system.users 中拉取单个用户记录的性能。#96699 (alistairjevans)。
改进
查询与 SQL 改进
- 在
UNION查询的多个分支中引用的 Materialized CTE 现在只会物化一次,并在所有分支之间共享。此前,每个分支都会获得各自的 CTE 副本,并将其内联后单独求值。#102107 (novikd)。 - 当探测端 (probe side) 的估算规模较小时,跳过 JOIN 运行时过滤器。新增设置
join_runtime_filter_min_probe_rows(默认值为1000) 用于控制该阈值 #104860 (vdimir)。 - 将
EXPLAIN [PLAN] actions=1, compact=1, pretty=1设为默认行为。#105036 (Fgrtue)。 - 降低了 LIMIT BY 正向形式 (LimitByTransform、LimitBySortedStreamTransform) 的取消延迟:KILL QUERY 和 Ctrl+C 现在可在单个数据块内中断处理,无需等待整个步骤完成。#106070 (rvasin)。
- JOIN 查询现已支持自动并行副本。#106073 (nickitat)。
- 新增异步指标 UntrackedMemory (可在
system.asynchronous_metrics中查看) ,用于报告线程已分配但尚未计入全局内存跟踪计数器的内存。每个线程会先在本地累积小额分配,再批量上报。这有助于解释MemoryTracking与进程实际内存使用量之间的差异。MEMORY_LIMIT_EXCEEDED错误消息现在也会包含未跟踪内存的大小,便于了解查询或服务器为何触及内存上限。#106386 (mstetsyuk)。 - 在构建插入管道时,如果 materialized view 的
TOtarget table 拒绝写入 (例如目标是View,或不支持事务) 导致INSERT失败,错误消息现在会指明该 materialized view 及其 target table,而不再仅报告底层存储错误。#107234 (groeneai)。 - 对具名
Tuple执行ALTER TABLE ... MODIFY COLUMN <col> Tuple(...)时,如果仅添加子字段,现在只需修改元数据,速度与顶层ADD COLUMN相当。该功能需通过SET allow_metadata_only_named_tuple_alter = 1启用。#107305 (amosbird)。 - 为
MaterializedPostgreSQL数据库引擎新增创建时设置materialized_postgresql_use_extended_date_and_time_types。默认 (启用) 情况下,PostgreSQL 的date/timestamp列会被推断为Date32/DateTime64;若在CREATE DATABASE时将其设为0,则会推断为范围更窄的Date/DateTime类型。该设置不适用于MaterializedPostgreSQL表引擎。#107428 (alexey-milovidov)。 - 当连接的估算结果行数来自提示或随机回退值而非表统计信息时,
EXPLAIN PLAN现在会将其标记为近似值 (~~...) ,便于识别缺少可靠统计信息、无法有效进行 JOIN 重排序的执行计划。#107666 (vdimir)。 - 向
MergeTree表执行INSERT时,在写入大量数据分片的过程中现在会响应查询取消和max_execution_time,不再出现被终止后仍长时间运行的情况。#107929 (al13n321)。 arrayFold现在会响应查询取消和max_execution_time。此前,对超长 array 执行 fold (例如arrayFold(acc, x -> arrayPushFront(acc, x), range(number), emptyArrayUInt64())) 时,整个 fold 过程都在单次函数调用中完成,无法中断,因此在 fold 结束之前,KILL QUERY和时间限制都不会生效。#108192 (groeneai)。- 新增按阶段划分的查询执行前
ProfileEvents:QueryParseMicroseconds、QueryAnalysisMicroseconds、QueryPlanBuildMicroseconds和QueryPipelineBuildMicroseconds。它们展示了查询执行前各阶段 (解析、分析、查询计划构建、管道构建) 的耗时情况,可在system.query_log和system.events中查看。#108282 (jrdi)。 - 如果
ALTER TABLE操作生成的表元数据会超过max_query_size,该操作现在会被预先拒绝,从而避免 DDL 分发和副本恢复等组件无法加载该表。#108283 (lockie)。 - 新增
ConstantJoin,用于笛卡尔连接以及由 analyzer 规划的常量谓词连接,因此在使用 analyzer 时,这些查询不会再因join_algorithm设置不兼容而失败。#108289 (antaljanosbenjamin)。 - 在
system.documentation中新增source列,记录定义各实体文档的源文件路径。该表现在还收录了压缩编解码器、profile events、当前指标、异步指标以及系统表本身 (及其列) 的文档,设置的文档中也新增了类型和默认值。#108346 (alexey-milovidov)。 - 如果在 WHERE 中提供
table和database过滤条件,system.iceberg_history将只列出匹配的数据库。当服务器上存在大量无关的远程数据库时,这可以节省一定时间。#108492 (Diskein)。 - 查询参数 (
{name:Type}替换) 现在可以用作设置值,既可用于查询 (如SELECT或INSERT) 的SETTINGS子句,也可用于独立的SET查询,例如SELECT ... SETTINGS max_threads = {threads:UInt64}和SET max_threads = {threads:UInt64}。#108760 (alexey-milovidov)。 - 支持在 EXPLAIN WHATIF 中计算跳数索引的综合收益。结果会显示数据比例,即所有现有适用假设索引效果的交集。#108934 (yariks5s)。
- 仅包含单个 CTE 的查询现在会采用与包含多个 CTE 的查询相同的换行和缩进格式。此前,
WITH a AS (...)会将 CTE 与WITH放在同一行,而包含两个或更多 CTE 时,WITH会单独占一行,且每个 CTE 均缩进。#109092 (groeneai)。 - 通过
File表引擎读取的本地 Parquet 文件现已支持查询条件缓存 (此前仅支持对象存储和数据湖) 。#109247 (alexey-milovidov)。 - 对于远程 (对象存储) Parquet 文件,查询条件缓存现在除路径外还以 ETag 作为键,因此原地覆盖对象后不会再返回过期的缓存结果。#109310 (alexey-milovidov)。
- 对于在
ON条件中被判定相等的INNER JOIN键,非限定引用 (例如SELECT id FROM a INNER JOIN b ON a.id = b.id) 不再被报告为歧义标识符,因为两侧的值必然相同。#109366 (alexey-milovidov)。 - 基于
QBit的转置距离函数 (L2DistanceTransposed、cosineDistanceTransposed、dotProductTransposed,以及对应的量化版本L2DistanceTransposedQuantized、cosineDistanceTransposedQuantized、dotProductTransposedQuantized) 现在可以接受长度超过待搜索维度数的参考向量,多余的尾随元素将被忽略。因此,在进行降维 (Matryoshka) 搜索时,可以直接复用完整的查询向量,无需先对其切片。#109388 (alexey-milovidov)。 - 新增合理性检查,确保分布式查询始终携带已知的客户端版本;若未携带,将抛出逻辑错误,而不是静默地向远程分片转发零版本。由服务器发起的查询 (后台刷写、流式消费者、字典重新加载、异步插入刷写) 现在会将服务器自身的版本作为发起方版本上报。#109408 (alexey-milovidov)。
- 此补丁修复了对 MergeTree 系列表引擎执行变更 (mutation) 操作时,在 where 子句中使用限定列名的问题。#109491 (Michicosun)。
- 分布式查询计划 (
make_distributed_plan) 现已支持非分区窗口函数 (OVER (ORDER BY ...)) 。此前,由于WindowStep无法序列化以供远程执行,任何包含窗口函数的查询都会失败;带有PARTITION BY的窗口目前仍不受支持。#109802 (VighneshPath)。 - 现在可以通过
ALTER DATABASE ... MODIFY SETTING = 'xxx'修改 one-lake catalog 的部分认证设置。#110019 (alesapin)。 - 当
IN右侧子查询仅返回一列,且该列是比左侧参数多一维的数组时,现在会将其解释为该数组元素的集合 (与数组字面量或返回数组的函数的处理方式相同) ,而不再报出令人费解的类型不匹配错误。例如,x IN (SELECT groupArray(x) FROM ...)现在可以正常工作。#110169 (alexey-milovidov)。 - 借助 TopK 动态过滤加速的查询 (
ORDER BY ... LIMIT k) 现在能更充分地利用查询条件缓存:即使应用了延迟物化,也会填充缓存;并且此类查询可以复用此前由具有相同WHERE谓词的普通查询写入的缓存条目。#110507 (shankar-iyer)。 - 当请求的表不存在时,
SHOW CREATE TABLE(以及SHOW CREATE VIEW/SHOW CREATE DICTIONARY) 现在会像SELECT查询一样,在错误消息中提示名称相近的表。#110633 (alexey-milovidov)。 - 新增 STREAM BOUNDED 修饰符,使流式查询仅读取第一个快照后即结束,而不再订阅后续更新。#110653 (SmitaRKulkarni)。
- 修复 PromQL 查询的查询结果缓存问题。
promql方言会绕过非确定性函数检查,可能返回锚定于now()的过期结果;而 Prometheus HTTP API (/api/v1/query、/api/v1/query_range) 则从未存储任何缓存条目。#110887 (nikitamikhaylov)。 EXPLAIN ANALYZE现在会报告 join 两侧各自的行数、匹配率、扇出,以及特定于算法的状态信息,例如哈希表内存占用和溢写情况。如需收集需要额外记录开销的匹配指标,请使用matches = 1。#110892 (Fgrtue)。- 修复了 pipeline 执行器中的 heap-use-after-free 问题:当查询在运行时移除处理器 (例如结合延迟读取或外部排序使用
FINAL) 时,可能导致服务器崩溃。该问题由 AST fuzzer 发现。#111017 (groeneai)。 - 修复了一个 use-after-free (段错误) 问题:当启用共享存储快照 (设置
enable_shared_storage_snapshot_in_query) 的查询从快照中剥离数据分片时会触发该问题,例如某个流式子查询所读取的MergeTree表正被同一查询的其他部分并发读取。#111192 (alexey-milovidov)。 - 对于在规划阶段即可确定数据源不会产生任何行的查询 (例如从空的
MergeTree表读取) ,现已支持分布式查询计划 (make_distributed_plan) 。此类查询此前会报错SUPPORT_IS_DISABLED。#111941 (groeneai)。 - 修复了当
WHERE子句包含多个AND条件时,被最后一个合取项以外的条件排除的粒度未写入查询条件缓存的问题。#112083 (shankar-iyer)。 - 降低了使用分桶共享数据序列化 (map_with_buckets 和 advanced) 写入 JSON 列时的峰值内存占用:写入时逐个将共享数据拆分到各个桶中,而不是同时物化所有桶。这主要对 Array(JSON) 列有益:对于标量 JSON,共享数据按粒度拆分 (受 index_granularity_bytes 限制) ,因此节省有限;而单个 Array(JSON) 粒度可能包含大量嵌套行,进而包含大量共享数据,此时逐桶拆分可显著降低峰值内存占用 #112172 (Avogar)。
- 内存预留调度 (experimental) 中,如果待处理的内存释放足以腾出超限预留增长所需的空间,则不再驱逐分配:驱逐决策现在会等待进行中的内存减少操作生效后再做出,从而避免在内存压力下不必要地终止查询。#112299 (serxa)。
SYSTEM DROP FILESYSTEM CACHE现在会并行删除缓存元数据键,从而加快大规模文件系统缓存的清理速度。新增的文件缓存设置drop_cache_threads用于控制删除工作线程的数量,默认值为 16;设为 1 时将在查询线程中执行删除。#112532 (kssenii)。- 列声明的修饰符 (
COMMENT、CODEC、STATISTICS、TTL、COLLATE、PRIMARY KEY以及列级SETTINGS) 现在在CREATE TABLE中可以按任意顺序书写,但每个修饰符最多出现一次。此前仅接受一种固定顺序,例如x UInt64 CODEC(ZSTD) COMMENT 'text'会被视为语法错误。在ALTER TABLE ... ADD COLUMN/MODIFY COLUMN中,所支持的修饰符 (COMMENT、CODEC、STATISTICS、TTL以及列级SETTINGS) 同样可以按任意顺序书写;ADD COLUMN中的列级SETTINGS,以及ADD COLUMN/MODIFY COLUMN中声明的STATISTICS,现在会真正生效,而不再被静默丢弃;这些ALTER命令中的COLLATE和PRIMARY KEY现在会抛出异常,而不再被静默忽略。#112788 (alexey-milovidov)。 - 对匹配大量表的
Merge表 (或merge表函数) 执行查询时,现在在构建各表查询计划的过程中即可响应KILL QUERY和max_execution_time,而无需等到所有子表的规划全部完成。#113415 (alexey-milovidov)。 - 在
timeout_overflow_mode = 'break'下,若对Merge表执行的SELECT超过max_execution_time,现在会立即停止为其余匹配的表构建查询计划,而不再先对每个匹配的表完成完整的查询分析后才停止。与该模式的文档说明一致,查询仍会正常结束,不会报错。#113642 (groeneai)。 - 读取
MergeTree时,如果某列的声明类型与其实际数据不一致 (类型来源混杂,例如ALTER TABLE ... MODIFY COLUMN的变更尚未完成时) ,服务器现在会抛出明确的异常,指明列名及两种结构,而不再执行未经检查的类型转换:此前,debug 和 sanitizer 构建会直接中止,仅给出一条不含列名的Bad cast from type A to B,而 release 构建则会悄无声息地访问不匹配的内存。#114087 (alexey-milovidov)。 - 默认启用
ie_join:join_algorithm的默认值现为direct,parallel_hash,hash,ie_join。如果JOIN的ON子句中仅包含不等式条件 (即在参与连接的表的表达式之间进行两次<、<=、>、>=比较) ,现在会使用基于排序的 IEJoin 算法执行,而不再采用带过滤条件的CROSS JOIN;同时,带此类条件的LEFT/RIGHT/FULL/SEMI/ANTI连接也已得到支持。由于ie_join位于列表末尾,只有在其他算法均不适用时才会使用它。#114327 (vdimir)。 - 将 OpenTelemetry trace 上下文传播到用于异步建立连接和执行远程查询的 fiber 中 (hedged requests、
async_socket_for_remote、async_query_sending_for_remote) 。分布式查询中远程查询的 span 现在会正确地以发起方的Connection::sendQueryspan 为父级,而不再直接挂到客户端提供的 trace 上下文下;此外,每次异步任务执行都会生成独立的 span。#114813 (diegomestre2)。 DROP DATABASE现在会同时依据加载依赖和引用依赖,按逆拓扑顺序删除表 (此前仅考虑加载依赖) ,因此即使DROP DATABASE执行中途发生崩溃,也不会遗留依赖项已被删除的表。#114952 (alexey-milovidov)。- 支持 PostgreSQL 风格的正则表达式匹配运算符:
~(match函数的别名) 、~*(不区分大小写匹配) 、!~和!~*(取反) 。通过 PostgreSQL 兼容协议连接到 ClickHouse 时,psql的\d、\dt、\dv命令现已可用,且查询失败不再导致连接中断。#115066 (alexey-milovidov)。 EXPLAIN WHATIF现在会说明跳过经验估算的原因:当empirical_status为unsupported时,会显示新增的empirical_reason行。#115140 (yariks5s)。- 当
join_algorithm设置所启用的连接算法均无法执行某个JOIN时,错误消息现在会列出已尝试的算法,以及失败 JOIN 的严格性和类型,而不再只是笼统地报告所有算法均不可用。#115226 (elkinal)。 - 当参考向量为整数数组字面量时 (例如
ORDER BY L2Distance(vec, [1, 2])) ,向量搜索查询现在可以使用向量相似度索引。此前,此类查询会静默回退为穷举扫描。#115255 (rschu1ze)。 - 如果创建锁文件的那次
BACKUP尝试在写入任何内容之前就失败了 (无论是在占用目标端时,还是在打开归档时) ,现在不会再在目标端遗留锁文件。此前,后续任何备份都无法匹配这种锁,导致对同一目标端的每次重试都会失败,只能手动删除该文件。备份到S3和Azure目标端时,也会以独占方式创建锁;若锁属于其他备份,则会报告为并发备份,而不是直接抛出存储返回的错误。#115387 (jkartseva)。 - 通过采样 (
opentelemetry_start_trace_probability) 启动的 trace 现在会回写到查询的客户端信息中,使远程查询、分布式二级查询以及 DDL 条目都加入同一个 trace,而不是各自启动互不关联的 trace。#115619 (diegomestre2)。 - 修复了对基于 Amazon S3 Tables (会自行管理表位置) 的 Iceberg 表执行
CREATE TABLE的问题。#115652 (scanhex12)。 - 自适应
GROUP BY聚合 (enable_adaptive_aggregator) 现在会评估延迟处理稀有键是否划算;当这些键或聚合参数过宽、复制得不偿失时,会回退到普通算法,因此对大字符串列的聚合 (例如按用户计算min(URL)) 可以达到普通算法的速度和内存开销。新增adaptive_aggregator_freeze_threshold_bytes,用于按字节限制每个线程冻结表的大小 (该阈值与键数量阈值中先达到者触发冻结) 。#115755 (nihalzp)。 - 新增设置
query_plan_aggregation_bucket_top_k(默认启用) ,用于开关以下查询计划优化:当最终聚合的输出交由带LIMIT n的ORDER BY处理时,仅物化每个两级桶中最优的n个分组。该优化现在也会显示在EXPLAIN输出中。#116124 (nihalzp)。 - 改进了
DESCRIBE查询对参数化视图的支持。新分析器支持在标量表达式中使用参数化视图。#68978 (novikd)。 - 类似
SELECT * FROM t WHERE id的查询现在会在id列上使用跳数索引。#89603 (adityachopra29)。 - 新增
query_plan_merge_expression_into_join设置,允许在 JOIN 重排序优化过程中将 Expression 步骤合并到 JOIN 步骤中。这样一来,JOIN 重排序便可跨越包裹连接的子查询进行 (例如 JOIN 位于带有计算列的子查询内部时) ,从而更好地优化复杂的连接树。#98533 (vdimir)。 - 在
system.grants表中新增is_wildcard列,用于标识授权是否使用通配符前缀匹配 (例如GRANT SELECT ON db*.*) 。此前,在system.grants中无法区分同一名称上的通配符授权与精确授权。#98577 (il9ue)。
函数与数据类型
- 新增设置
allow_lossy_numeric_supertype(默认禁用) 。启用后,当if、multiIf、coalesce、ifNull、array和map作用于不存在无损公共类型的数值参数时 (例如Decimal与Float64,或Int64与Float64) ,结果类型将解析为数值超类型Float64而非Variant,从而可用于sum、avg、min和max等聚合函数。相关聚合函数的错误消息中现在也会提示该设置名称。#107236 (groeneai)。 SOME/ALL数组量词 (expr OP SOME(array)/expr OP ALL(array)) 现已支持关键字比较谓词IS DISTINCT FROM和IS NOT DISTINCT FROM,以及字符串搜索谓词LIKE、ILIKE、NOT LIKE、NOT ILIKE和REGEXP,这些谓词会被重写为arrayExists/arrayAll。#107454 (alexey-milovidov)。- 新增
input_format_json_max_object_size设置,用于在解析时限制 JSON 对象的大小。#107669 (Avogar)。 - 修复了打开 SQLite 数据库失败时出现的内存泄漏问题 (例如为
sqlite表函数或SQLite数据库引擎指定了无法打开的路径时) 。#107807 (alexey-milovidov)。 QBit数据类型现已支持length函数,该函数以常量形式返回向量的维度。#108071 (alexey-milovidov)。- 支持通过
CAST将QBit转换为Array,以还原原始向量。这是现有Array到QBit转换的逆操作。#108072 (alexey-milovidov)。 MySQL数据库引擎、表引擎和表函数现在会将 MySQL 的空间列类型 (LINESTRING、POLYGON、MULTILINESTRING、MULTIPOLYGON以及通用的GEOMETRY) 映射为相应的 ClickHouse 几何类型,而不再映射为String。该行为由mysql_datatypes_support_level设置中新增的geometry标志控制,默认启用。POINT仍始终转换为Point。通用的GEOMETRY列映射为统一的Geometry类型;若所读取值的子类型在 ClickHouse 中没有对应类型 (MULTIPOINT、GEOMETRYCOLLECTION) ,则会在读取时抛出异常。#108944 (alexey-milovidov)。- 默认采用精确 (取最接近的可表示值) 的浮点数解析算法,并将
precise_float_parsing设置的作用范围扩展到输入格式 (CSV、TSV、JSON、VALUES 等) 和数值字面量,而不再仅限于toFloat*/CAST。如需恢复之前的行为 (某些情况下更快,但精度较低) ,请设置precise_float_parsing = 0。#109086 (Algunenano)。 - 支持通过
reinterpret将由定长元素组成的Array重新解释为String,这是现有通过reinterpret将String/FixedString重新解释为Array的逆操作。#109383 (alexey-milovidov)。 - 允许在元素类型和/或 stride 不同的
QBit类型之间执行CAST,前提是维度保持不变 (例如对QBit(Float32, N)类型的值执行CAST(x AS QBit(Float64, N))) 。仅更改 stride 的转换是无损的;更改元素类型的转换遵循相应的Array转换语义 (例如Float32转换为BFloat16可能会损失精度,而accurateCast/accurateCastOrNull会拒绝无法精确表示的行) 。#109387 (alexey-milovidov)。 - 函数
quantizeBFloat16ToInt8和dequantizeInt8ToBFloat16除现有的标量重载外,现在还接受Array和QBit参数,对整个向量应用 Lloyd-Max 编解码器 (返回对应元素类型的Array/QBit) 。#109398 (alexey-milovidov)。 parseDateTime/parseDateTime64(及其OrZero/OrNull变体) 中的 MySQL 风格格式说明符%f现在接受 1 到 6 位小数,并与 MySQL 的STR_TO_DATE一样按左对齐的微秒进行解释,不再要求恰好为 6 位。同时修复了内置函数文档示例中PrettyCompact表格未对齐的问题。#109421 (alexey-milovidov)。basic统计信息中的NullCount子统计项已重命名为DefaultCount:build不再统计Nullable列中的NULL行,而是通过IColumn::getNumberOfDefaultRows统计等于该列类型固有默认值的行数。#109977 (hanfei1991)。- 对于较少使用的混合类型组合 (
Decimal与不同宽度的整数,以及涉及Int128/UInt128/Int256/UInt256的组合) ,比较和算术运算改为先转换为公共类型再执行,不再为每种类型组合单独编译专用内核,从而使二进制文件体积减少约 10.5 MB。相同类型组合、常用组合以及受内存带宽限制的plus/minus/multiply仍保留专用内核;结果、结果类型和异常情况均保持不变。#110131 (alexey-milovidov)。 - 当 SQLite 数据库被其他连接锁定时,从
SQLite表引擎或sqlite表函数读取数据不再忙等并占满一个 CPU 核心。现在读取操作在等待锁期间处于空闲状态,且仍可取消。#110248 (groeneai)。 - 日志和异常消息中的耗时、速率和比率值现在四舍五入保留三位有效数字,诸如
1.345844286 sec.之类的数值不再以全精度输出。#110277 (alexey-milovidov)。 - 修复了
MergeTree在跳过前导行后读取带有独立 size 流的String列时,可能返回错误数据或越界读取子流缓存的问题。同时修复了并发或重复读取以 map shared-data 序列化方式存储的JSON子对象时可能返回错误数据的问题。#110471 (alexey-milovidov)。 PostgreSQL表引擎和postgresql表函数现已支持SETTINGS子句 (例如SETTINGS postgresql_connection_pool_size = 50) ,在功能上与MySQL引擎看齐。#110614 (alexey-milovidov)。- 函数
bitmaskToArray和bitmaskToList现已支持(U)Int128和(U)Int256参数。对于大整数参数,函数bitPositionsToArray的运行时间现在与置位数量成正比,而不再取决于最高置位的位置。#110743 (raimannma)。 - 修复了 GCD 编解码器处理含负数的有符号定宽值时的问题。此前它直接基于有符号值计算除数,可能找不到公约数,从而显著降低有符号整数列和小数列的压缩效率。现在对于有符号类型,会基于绝对值计算除数,同时无符号类型及解压缩的现有行为保持不变。#113798 (kshcherbatov)。
- 带有
PARTITION BY的窗口函数现在可以在make_distributed_plan下运行。在查询计划结构允许的情况下,窗口会在多个桶之间并行执行,每个桶均接收完整的分区。#114111 (VighneshPath)。 - 外部 Nullable 定宽聚合方法现改用 64 位哈希函数 (避免极高基数聚合时出现严重的哈希冲突) 。#114210 (nickitat)。
- 作用于
LowCardinality列的x IN (subquery)现在返回LowCardinality(UInt8),与x IN (literal list)的返回类型一致。此前这两种形式返回的类型不同,包含此类IN的分布式查询计划需要在计划类型检查中做特殊处理。#114229 (davenger)。 - 支持在
JSON数据类型、JSONExtract和isValidJSON中解析超出 64 位范围的整数。此类值会被读取为Int128/UInt256等宽整数类型,而不再导致整个文档被拒绝。#114379 (Avogar)。 - 新增
keyword作为文本索引分词器array的别名,以提升与 OpenSearch、Elasticsearch、SolR 和 Lucene 的兼容性。#115507 (rschu1ze)。 - 函数
toDateOrNull、toDateTimeOrNull和toDateTime64OrNull现在接受所有原生整数类型的整数参数 (解析方式与toDate、toDateTime和toDateTime64相同,并可选传入时区参数) ,对于超出结果类型范围的值返回NULL。例如,toDateTimeOrNull(1583851242, 'Asia/Shanghai')返回2020-03-10 22:40:42,而toDateTimeOrNull(4294967296)返回NULL。#79791 (jitendra1411)。
存储、数据湖与对象存储
- 新增可选启用的文件系统缓存淘汰相关 Prometheus 指标 (
filesystem_cache_evictions_total、filesystem_cache_evicted_bytes_total、filesystem_cache_evicted_segment_hits、filesystem_cache_evicted_segment_size_bytes,以及带有user_id标签的按用户变体) ,按缓存分别通过system.dimensional_metrics、system.histogram_metrics和 Prometheus 端点对外暴露。这些指标由缓存磁盘配置中的expose_prometheus_eviction_metrics和expose_prometheus_eviction_metrics_per_user设置控制 (默认均关闭) ,并可在运行时通过SYSTEM RELOAD CONFIG开启或关闭。#105020 (sacheendra). - 当目标表为
MergeTree系列引擎时,Alias引擎现已支持并行副本读取。#107830 (nauu). - 在 Azure Blob 存储的“先读后写”复制 (备份在原生复制不可用时使用) 中,将并发暂存的分片数量限制为 max_inflight_parts_for_one_file,避免并行复制大量大文件时内存使用量过高。#108232 (SmitaRKulkarni).
- HDFS 存储支持
_etag虚拟列 #108255 (zhangyifan27). - 在
system.backups和system.backup_log中新增settings和engine_settings列。settings展示某次操作所请求的备份/恢复专用设置 (例如allow_s3_native_copy、deduplicate_files、structure_only) ,engine_settings则展示备份引擎读取器/写入器实际生效的设置 (例如allow_native_copy等 S3 请求设置,在与端点配置合并后可能与所请求的值不同) 。借此即可查看BACKUP/RESTORE操作实际运行时采用的设置。#108334 (jkartseva). - 新增
system.s3_queue_metadata和system.azure_queue_metadata,用于查看已注册的S3Queue和AzureQueue表在 Keeper 中的状态,包括已处理、处理中和失败的文件数。#108522 (kssenii). - 将文本索引头部缓存的内存使用量降低至原来的 1/2 到 1/2.5。缓存 (由设置
text_index_header_cache_size控制) 可容纳更多数据分区片段的头部信息,从而减少文本搜索查询的磁盘读取。#109332 (CurtizJ). - 为
INFORMATION_SCHEMA视图新增 MySQL 兼容列:SCHEMATA.DEFAULT_COLLATION_NAME和DEFAULT_ENCRYPTION;TABLES.ENGINE及相关 MySQL 列;以及COLUMNS.COLUMN_KEY、PRIVILEGES、GENERATION_EXPRESSION、SRS_ID。这样,兼容 MySQL 的客户端在执行目录自省查询时便不会再遇到UNKNOWN_IDENTIFIER错误。#109351 (alexey-milovidov). - 降低了包含大量数据分区片段的
MergeTree表的内存使用量:由 schema 派生的每个 part 的元数据 (列列表、列描述、序列化信息以及列子流) 现在在同一张表的各个 parts 之间共享,而不再复制到每个 part 中。对于包含大量小 parts 的宽表,效果最为明显。#109816 (Algunenano). - 新增设置
use_projection_index_in_read_pools(默认禁用) 。启用后,被 projection 索引完全过滤掉的 mark ranges 会在MergeTree读取池中被直接丢弃,不再为其创建读取任务,而不是在读取过程中逐个粒度跳过。这样可以避免为不会被读取的数据创建读取任务和初始化读取器,并使读取任务的大小按保留下来的标记数计算。#110291 (KochetovNicolai)。 - 降低了
MergeTree中按分片执行的主键二分查找诊断信息的详细程度,将其从 trace 级别日志下调为 test 级别日志。#110324 (alexey-milovidov)。 - 修复了基于 TLS (HTTPS、S3) 的池化 HTTP keep-alive 连接出现虚假重连的问题。此前的失效连接检查对套接字使用
poll,会把带有未读 TLS 握手后记录 (会话票据或KeyUpdate) 的活跃安全连接误判为已关闭;现在对普通套接字改用非阻塞的MSG_PEEK,对 TLS 套接字改用SSL_peek/SSL_has_pending,并且还能正确识别正常的 TLS 关闭以及仅部分到达的 TLS 记录。#110402 (alexey-milovidov)。 - OneLake 目录现在支持使用 OAuth refresh token 续期访问令牌。#110413 (alesapin)。
- 新增
DuplicationDataHashComputationsProfileEvent,用于统计对插入*MergeTree表的块进行去重时所执行的按列数据哈希计算次数。#111173 (valerypetrov)。 - 通过存储抽象层将 UNIQUE KEY 索引 SST 直接写入分片,不再先暂存到本地临时文件。#111189 (JingYanchao)。
- 支持在本地磁盘上并发写入 Iceberg 表:
LocalObjectStorage现已实现条件写入,因此通过version-hint.text发布新快照的 compare-and-swap 操作可在本地磁盘上正常工作,并发写入方之间不会再互相覆盖丢失更新。#112556 (alexey-milovidov)。 S3客户端的 bucket 区域缓存现在同样适用于数据湖目录;此前每次向其发出请求时都会重新解析区域。#113330 (scanhex12)。- Azure 客户端侧的网络故障 (连接重置/被拒、DNS 和 TLS 错误) 现在会作为传输错误进行重试,而不再以人为构造的
500错误抛出,与 S3 客户端的行为保持一致。#115269 (arsenmuk)。
格式与摄取
- HTTP 接口现已支持 snappy 压缩 (
Accept-Encoding: snappy) ,并新增snappy_mode设置,可为通用file/urlsnappy I/O 选择 Hadoop snappy 块格式或 snappy 帧格式。#100752 (alexey-milovidov)。 - 新增设置
input_format_csv_missing_nullable_as_empty_string(默认禁用) 。启用后,CSV 输入中缺失的Nullable(String)值将读取为空String,而非NULL,且不受input_format_csv_empty_as_default的影响。#107577 (alexey-milovidov)。 - 使用
input_format_protobuf_oneof_presence处理 protobuf 消息时,不再要求标签精确匹配,从而支持 schema 变更。#109174 (ilejn)。 - 移除了基于 Apache Arrow 的旧版 ORC 读取器。ORC 输入格式现在始终使用 ClickHouse 原生解码器 (此前已是默认选项) 。
input_format_orc_use_fast_decoder设置已废弃 (仍可设置,但不再生效) 。#110074 (alexey-milovidov)。 - Hive 引擎现改用 ClickHouse 原生 ORC 读取器读取 ORC 文件元数据 (min/max 索引、行数) ,不再依赖 Apache Arrow ORC adapter。#110086 (alexey-milovidov)。
安全、访问与可观测性
- 在
system.tables表中新增列skipping_indices_types,列出每张表上定义的数据跳过索引的各个类型 (已去重) 。#106388 (CurtizJ)。 max_threads等设置的自动值现在在system.settings中显示为auto(8),而不再是'auto(8)';外层的单引号是长期以来固化在该值中的历史遗留问题。跨版本兼容性不受影响:解析从旧版本服务器接收的设置时,仍接受旧的带引号形式。#108657 (alexey-milovidov)。- 在
system.documentation中,空的设置默认值现在显示为 空字符串,而不再是一对空的反引号。#108708 (alexey-milovidov)。 system.documentation中的设置文档 (由内置的/docs页面和help命令展示) 现在包含其默认值的变更历史:包括该设置引入时的版本,以及此后默认值的每一次变更,并列出变更前的值、变更后的值及变更原因。#112177 (alexey-milovidov)。- 现在可以从系统表
system.statements中查询所有 SQL 语句的文档 (如名称、语法、描述、示例) 。#115341 (rschu1ze)。
设置与配置
- 新增服务器设置
memory_worker_rss_speculative_reserve_ratio(默认值为1.0,在 sanitizer 构建中为0) ,使全局内存跟踪器在每次MemoryWorker周期中,在观测到的 RSS 基础上额外推测性地预留ratio * min(resident - previous_resident, resident - tracked)。当两次采样之间 RSS 的增长速度超过跟踪器的记账速度时,该机制会让跟踪器的数值适当偏高,使内存分配更早触发MEMORY_LIMIT_EXCEEDED,从而降低内核 OOM-killer 抢先介入的可能性。将该比率设为0即可禁用推测预留。sanitizer 构建默认使用0,因为在这类构建中,resident - tracked差值主要来自 sanitizer 的影子内存。#104976 (alexey-milovidov)。 - 文本索引的延迟倒排列表应用模式不再是实验性功能,无需设置
allow_experimental_text_index_lazy_apply,即可通过text_index_posting_list_apply_mode = 'lazy'启用。密度阈值设置已从text_index_density_threshold重命名为text_index_lazy_intersection_density_threshold。#108814 (CurtizJ)。 merge_selector_enable_heuristic_to_lower_max_parts_to_merge_at_once设置现已默认启用:合并选择器会根据分区的填充程度,自动降低单次合并的 parts 数量上限。#110726 (Michicosun)。- PostgreSQL wire 协议现将 PostgreSQL 清理命令
RESET、UNLISTEN和DISCARD作为空操作处理,不再报语法错误。这提升了与 Skunk 等驱动程序的兼容性,此类驱动会在建立和清理连接时发送RESET ALL和UNLISTEN *。#110780 (alexey-milovidov)。 - AI 文本函数 (
aiGenerate、aiClassify、aiExtract、aiTranslate) 现在会拒绝被截断或其他不完整的提供方响应 (例如模型达到max_tokens上限时) ,而不再静默返回部分输出。具体行为由ai_function_throw_on_error设置决定。#111830 (george-larionov)。 - 改进低精度模式下的
L2DistanceTransposedQuantized、cosineDistanceTransposedQuantized和dotProductTransposedQuantized:使用高斯条件均值前缀质心重建p < 8QBit(Int8)编码。全精度 (p = 8) 仍保持比特级精确;低精度下的近似距离可能有所变化,召回率和延迟方面的收益因工作负载而异。#111867 (skuznetsov)。 write_snapshot_version设置现已支持热重载。#112150 (alesapin)。- 为纤程栈 (用于与远程副本进行异步通信) 新增可观测性支持:profile events
FiberStackAllocs、FiberStackAllocBytes、FiberStackAllocNanoseconds、FiberStackFreeNanoseconds,以及指标FiberStacks、FiberStackBytes。#114541 (alexey-milovidov)。 - Prometheus 远程写入协议现已支持异步插入:来自多个并发远程写入请求的数据会先合批,再生成 parts,具体行为遵循
async_insert设置 (默认启用;在 handler URL 中添加async_insert=0可保留同步行为) 。只有当数据刷新到目标TimeSeries表的所有内部表之后,请求才会得到确认。#115688 (nikitamikhaylov)。
其他改进
- 新增两个设置
shrink_over_allocated_columns_min_waste_ratio和shrink_over_allocated_columns_min_waste_bytes,可使 INSERT 在物化和写入分片之前,将过度分配的列 (即变长列按 2 的幂增长、导致预留内存超出实际使用内存的列) 收缩至合适大小,从而降低峰值内存占用。默认禁用。#112161 (Avogar)。 - 对于
TTLDrop合并,完全跳过数据读取步骤,以避免内存使用量过高,尤其是读取/预取缓冲区的内存分配。#105859 (Avogar)。 dotProduct新增对BFloat16的支持,并通过对 SIMD 路径进行批处理提升了点积性能。#106569 (nickitat)。max_named_collection_num_to_throw、max_table_num_to_throw、max_replicated_table_num_to_throw、max_view_num_to_throw、max_dictionary_num_to_throw和max_database_num_to_throw现在无需重启服务器即可修改。#106821 (UberDever)。- 由
allow_experimental_delta_lake_writes控制的DeltaLake表写入功能已升级为 Beta。#107034 (kssenii)。 - 新增
uniq_v2列统计信息类型,它基于uniqCombined64sketch,是uniq的轻量级替代方案。#107863 (hanfei1991)。 - 新增 ProfileEvents
DistributedPlanRemoteTasks、DistributedPlanLocalExecution和DistributedPlanHostsUsed,用于观测 make_distributed_plan 的执行情况。#107985 (shankar-iyer)。 - 发往 OneLake 等 REST 数据湖目录的请求现在会携带 ClickHouse
User-Agent请求头。#108117 (scanhex12)。 MVTEncodeGeom现在会在裁剪前将几何图形吸附到整数像素网格,并使用wagyu裁剪多边形,从而确保裁剪输出有效 (自相交的环会被修复) 且边缘对齐,与 PostGISST_AsMVTGeom的结果一致。#108248 (saarthak2002)。- 全局启用全部三种文本索引缓存——此前它们仅在查询内部启用。此外,倒排列表缓存大小现设为零 (实际上相当于再次禁用该缓存) ,因为倒排列表体积较大,缓存成本过高。#108274 (rschu1ze)。
- 在加载表之前即启动 Prometheus 端点 (适用于仅含指标的配置) 和异步指标收集,以便在可能耗时较长的元数据加载阶段也能观测指标。#108402 (cwurm)。
- 二元数学函数支持 BFloat16 #108442 (zhangyifan27)。
- 转置向量距离函数
L2DistanceTransposed、cosineDistanceTransposed和dotProductTransposed现在会对Nullable(QBit)列应用部分位平面读取优化,仅读取所需的位平面,而无需读取整列。#109358 (alexey-milovidov)。 arraySum、arrayAvg和arrayProduct现已支持BFloat16类型的数组。#109420 (alexey-milovidov)。- 函数
L1Normalize、L2Normalize、LinfNormalize和LpNormalize(及其别名) 现在除元组外也支持数组,与L2Norm及距离函数的行为保持一致。#110052 (alexey-milovidov)。 - 池化连接在每次使用前不再发送 ping。此前每个复用的连接都会额外产生一次
Ping-Pong往返,此项改动将其消除,从而降低了分布式查询和clickhouse-benchmark的延迟。失效的池化连接会通过零超时轮询 (一种非阻塞检查,不会增加往返) 检测出来,并通过重新连接恢复。#110068 (alexey-milovidov)。 - 在分布式索引分析中,将较大的数据片段 (part) 列表作为标量发送 (避免因 max_ast_elements/max_query_size 限制而可能导致的失败,并消除 AST 解析开销) 。#110419 (azat)。
- 现在在 Playground 中点击云朵图标会在新标签页中打开 ClickHouse 网站,避免查询运行时丢失进度。#110422 (williamhatcher)。
- 将
auto_statistics_types的默认值从basic, uniq更改为basic, uniq_v2。#110878 (hanfei1991)。 - 当
RWLockImpl::getLock()的重入断言触发时 (RWLock is already locked in exclusive mode/Cannot acquire exclusive lock while RWLock is already locked) ,错误消息现在会列出当前持有该锁的其他query_id,以及发起请求的query_id已持有的锁数量,便于诊断此类锁顺序错误。#110971 (groeneai)。 randomHadamardTransform现在可以对最大奇因子不超过 64 的任意向量长度 (例如嵌入模型中常见的3584 = 512 * 7) 计算精确且保持长度的变换,在此前支持的2^N、2^k * {12, 20}和2^k * 9系列基础上进一步扩展。对于无法精确表示的长度,完整变换现在会抛出异常,而不再静默地零填充为更长的向量;如需计算任意长度的截断投影,请传入output_dims。#111006 (alexey-milovidov)。- 通过 HTTP 接口发生
ACCESS_DENIED异常时,现在返回 HTTP 状态码403 Forbidden(而非500 Internal Server Error) 。#111043 (Schum-io)。 UTMToGeo的第四个参数现在除整数半球标志外,还可接受geoToUTM返回的 MGRS 纬度带字母,因此geoToUTM的结果可直接传给UTMToGeo进行无损往返转换。#111521 (alexey-milovidov)。MaterializedPostgreSQL现在在更新时会保留未更改的 PostgreSQLTOAST值,而不再将其替换为默认值。#111552 (OrpheusAgent)。- 新增
text_index_max_processed_tokens_before_flush和text_index_max_memory_usage_before_flush设置,用于控制文本索引构建器何时刷写临时分段。#111573 (rorylshanks)。 - 新增 STREAM UNORDERED 修饰符:跳过每个快照内按提交顺序进行的排序 #111794 (SmitaRKulkarni)。
- 现在设置
make_distributed_plan=1时会禁用尚不支持的功能。#112463 (alesapin)。 - 当 stdout 为 tty 时,不再向 INTO OUTFILE 写入 ANSI 转义序列 #113252 (azat)。
- 将
allow_experimental_delta_kernel_rs重命名为allow_delta_kernel_rs,旧名称作为别名保留。#113476 (kssenii)。 - 新增设置
enable_alp_codec、enable_sz3_codec、enable_zxc_codec和enable_quantized_codec,可分别单独启用各个实验性压缩编解码器。#113824 (rienath)。 - 发生栈溢出时会报告错误,而不再静默崩溃:致命信号处理程序现在运行在备用信号栈上,因此即使出错线程的栈空间已耗尽,
SIGSEGV、SIGABRT、SIGILL、SIGBUS、SIGSYS、SIGFPE和SIGTRAP也能生成堆栈跟踪。#113927 (groeneai)。 - 即时查询和范围查询现已支持 Prometheus HTTP API 的 lookback_delta 参数。#113971 (fallintoplace)。
- QueryRunner 表现在会按需启动工作线程,并在空闲后释放,不再在表的整个生命周期内一直占用线程。#114522 (mstetsyuk)。
- 使用 WHATIF 索引时,由投影提供的基线现在会针对每个候选项报告
not_applicable,而不会导致语句执行失败。#114846 (yariks5s)。 - 优化针对同一表达式包含多个比较条件的 AND 链:检测相互矛盾的条件 (例如
a < 3 AND a > 5→false) ,并裁剪冗余条件 (例如a = 3 AND a < 5→a = 3) 。#99736 (wudidapaopao)。
缺陷修复
MergeTree、复制与存储相关修复
- 修复了
MergeTree中ALTER TABLE ... RENAME COLUMN与并发执行的OPTIMIZE TABLE ... FINAL(或任意后台合并) 之间的竞态问题,该问题可能导致被重命名列的数据在无任何提示的情况下被替换为默认值。现在,在发布新的内存元数据以及在current_mutations_by_version中注册重命名变更这两个操作期间,会始终持有currently_processing_in_background_mutex,从而消除了二者之间的竞态窗口。#104822 (groeneai)。 - 修复了在投影中同时使用 GROUP BY、ORDER BY 和
arrayJoin时查询结果不正确的问题。#101775 (Onyx2406)。 - 无效的 Azure 上传大小设置 (例如
azure_min_upload_part_size = 0或azure_max_blocks_in_multipart_upload = 0) 现在会被提前拒绝,并给出明确的错误信息,而不会再在写入路径深处触发内部异常 (second_size > 0) 。此改动同时适用于查询设置和 Azure 磁盘配置。#103394 (statxc)。 - 在两个粒度设置不兼容 (一个为自适应,一个为非自适应) 的
MergeTree表之间运行ALTER TABLE ... MOVE/REPLACE/ATTACH PARTITION时,现在会抛出BAD_ARGUMENTS,而不是LOGICAL_ERROR。#103881 (groeneai)。 - 修复了
KILL QUERY/KILL MUTATION/KILL PART_MOVE_TO_SHARD/KILL TRANSACTION抛出LOGICAL_ERROR“Expected one block from input stream” 的问题。该问题出现在其WHERE子句包含逐行子查询,或max_block_size过小、导致针对相关system.*表的内部SELECT输出多个块的情况下。#104927 (groeneai)。 - 修复了可刷新materialized view (
MATERIALIZED VIEW ... REFRESH ...) 中的泄漏问题:刷新任务通过EXCHANGE TABLES轮换出的临时内部表,若大小超过服务器的max_table_size_to_drop,便无法被删除。此后每次刷新都会再创建一个新的临时内部表,而之前的表仍无法清理,导致视图的数据目录持续膨胀,直至磁盘耗尽。现在,刷新任务内部执行的删除操作会绕过max_table_size_to_drop和max_partition_size_to_drop;对于用户针对视图本身发起的DROP TABLE,这些安全限制依然有效。#105106 (groeneai)。 - 修复了以下问题:对于 sorting key 中包含
SimpleAggregateFunction(或其他仅在allow_suspicious_primary_key = 1时才允许的类型) 的MergeTree表,执行不会更改 sorting key 的ALTER查询 (如修改设置、注释、编解码器,添加非键列等) 时,会意外报出DATA_TYPE_CANNOT_BE_USED_IN_KEY错误。#105111 (groeneai)。 OPTIMIZE ... DRY RUN因查询超时 (max_execution_time配合timeout_overflow_mode = 'break') 而中断时,现在会返回TIMEOUT_EXCEEDED,而不再返回与rows_sources相关的逻辑错误 (该错误在 debug 和 sanitizer 构建中会导致服务器中止) 。#107114 (groeneai)。- 修复了在启用
use_hive_partitioning=1读取 Hive 分区文件时,若WHERE/PREWHERE子句过滤的是真实 (非虚拟) 列,且同时选择了 Hive 分区列,会报出NOT_FOUND_COLUMN_IN_BLOCK的问题。#107505 (groeneai)。 - 修复了当
toStartOfDay、toStartOfISOYear、toDaysSinceYearZero、toRelativeSecondNum、toRelativeMinuteNum、toRelativeHourNum、toRelativeWeekNum、toRelativeDayNum、toMonthNumSinceEpoch或toYearNumSinceEpoch作用于Date32键列,且该列包含超出函数可表示范围的日期 (尤其是1970-01-01之前的日期) 时,主键和分区裁剪出错进而导致查询结果错误的问题。这些函数会向主索引声明自身具有单调性,但此前遇到此类参数时会发生回绕,导致索引可能裁剪掉实际包含匹配行的 granule。现在,这些函数会在结果类型的边界处饱和,并在整个Date32范围内保持单调,从而确保裁剪正确。#108018 (nihalzp)。 - 修复了
CREATE TABLE dst AS src SETTINGS ...(以及带有ORDER BY/PARTITION BY但未显式指定ENGINE的类似写法) 会静默丢弃源表的引擎、存储子句 (例如表TTL和各类键) 以及设置的问题。现在,引擎以及未被覆盖的存储子句会从源表继承,所指定的设置则会在源表设置的基础上进行合并。#108085 (alexey-milovidov)。 - 修复了在基于 Windows 的文件系统 (WSL、CIFS/SMB、Docker Desktop 绑定挂载) 上向
MergeTree表执行INSERT时报错filesystem error: in rename: Permission denied的问题。该问题的原因是分片写入器在重命名分片目录时仍未关闭文件描述符。#108089 (alexey-milovidov)。 - 修复了附加时带有旧版
hypothesis跳数索引 (一种已移除的索引类型,仅为兼容ATTACH而保留) 的 MergeTree 表陷入卡死的问题。此前,在此类表上执行轻量级DELETE、OPTIMIZE、普通INSERT或带过滤条件的SELECT时会报错ILLEGAL_INDEX(“Index of type ‘hypothesis’ is no longer supported”) ,且DELETE变更会无限重试。现在,该失效索引将被视为惰性对象:在合并/变更期间原样保留,在插入和查询规划时被跳过,并且仍可通过ALTER TABLE ... DROP INDEX删除。#108217 (groeneai)。 - 修复了在启用并行副本时从
MergeTree表查询虚拟列 (包括在asterisk_include_virtual_columns = 1时通过SELECT *查询) 出现NOT_FOUND_COLUMN_IN_BLOCK错误 (例如Column _part not found) 的问题。#108451 (groeneai)。 - 修复了
ATTACH PARTITION ... FROM会拒绝主键等价但声明方式不同 (一个显式声明PRIMARY KEY,另一个由ORDER BY隐式推导) 的表的问题。#108590 (jordiori)。 - 现在,所有受支持的基于哈希的连接路径 (包括会自动溢写到磁盘的连接) 都会遵循
join_any_take_last_row设置。#108936 (antaljanosbenjamin)。 - 修复了在启用
query_plan_optimize_lazy_final且WHERE过滤条件被部分下推到PREWHERE(通过optimize_move_to_prewhere_if_final) 时出现NOT_FOUND_COLUMN_IN_BLOCK错误的问题。惰性 FINAL 优化不再从存储层请求由 prewhere 计算得出的谓词列。#109073 (groeneai)。 - 修复了在会话设置
optimize_respect_aliases = 0时,基于表级ALIAS列执行ALTER TABLE ... ADD PROJECTION会导致表无法使用的问题 (后续INSERT会失败并报UNKNOWN_IDENTIFIER、“Missing columns” 错误) 。#109091 (groeneai)。 - 修复了在旧版 analyzer (
allow_experimental_analyzer = 0) 下,对与其他表 JOIN 的Merge引擎表执行ORDER BY ALL(或GROUP BY ALL) 时触发空指针断言的问题 (TreeRewriter::analyzeSelect中的px != 0,在 debug 和 sanitizer 构建中会导致服务器中止) 。#109139 (groeneai)。 - 修复了当关联条件仅出现在子查询投影中、且同时存在非关联的
WHERE子句时,关联EXISTS子查询和标量子查询返回错误结果的问题 (子查询可能对每一行都求值为 false /NULL) 。修复 https://github.com/ClickHouse/ClickHouse/issues/105760。[#109186](https://github.com/ClickHouse/ClickHouse/pull/109186) (novikd)。 - 修复了在启用
enable_block_number_column或enable_block_offset_column设置时,合并带有 projection 的MergeTree表会生成包含多余_block_number/_block_offset列的 projection parts 的问题。合并后的 projection part 与 projection 定义及插入生成的 projection parts 不再一致,导致CHECK TABLE和OPTIMIZE ... DRY RUN将其报告为已损坏 (CORRUPTED_DATA) 。#109284 (groeneai)。 - 修复了当 MergeTree 表在持久虚拟列
_block_number或_block_offset上存在隐式 min-max 索引 (由add_minmax_index_for_block_number_column/add_minmax_index_for_block_offset_column启用) 时,执行ALTER TABLE ... RENAME/ADD/MODIFY COLUMN报UNKNOWN_IDENTIFIER错误的问题。#109428 (groeneai)。 - 修复了在
Widepart 上执行需重写整个 part 的变更 (例如对MATERIALIZED列执行ALTER TABLE ... DROP COLUMN) 后,跳数索引从数据 part 中丢失 (或CHECK TABLE失败并报UNEXPECTED_FILE_IN_DATA_PART) 的问题。#109616 (groeneai)。 - 修复了使用
ALTER TABLE ... APPLY PATCHES物化轻量级更新后,跳数索引 (text、bloom_filter等) 和 projection 未同步更新的问题。此前,依赖于补丁所更新列的索引和 projection 文件不会随之更新,因此使用它们的查询可能返回错误结果 (例如hasToken漏掉已更新的行,或在已应用的补丁 part 被移除后,projection 返回过时的聚合结果) 。#109709 (groeneai)。 - 修复了引用
_sample_factor虚拟列的变更在执行中途失败并报Unexpected const virtual column: _sample_factor、导致变更卡住的问题。现在变更会将其读取为1,与不带SAMPLE的查询返回的值一致。#109813 (groeneai)。 - 修复了带有
GROUP BY GROUPING SETS的查询 (或包含它的标量子查询或变更子查询) 在force_aggregation_in_order = 1下运行时引发的两个错误:旧版 analyzer (enable_analyzer = 0) 下的Trying to get name of not a column: ExpressionList,以及在 analyzer 下、设置了enable_memory_bound_merging_of_aggregation_results = 1的分布式查询中出现的Memory bound merging of aggregated results is not supported for grouping sets.。#109862 (groeneai)。 - 修复了
use_constant_folding_in_index_analysis的三个问题:当表设置了part_minmax_index_columns = 'with_block_number_offset'时,使用普通投影的SELECT可能因逻辑错误Invalid partition key size而中止;对取模分区键 (如PARTITION BY id % 200) 进行过滤时返回错误结果 (静默丢弃行) ;以及在max_threads > 1的情况下,使用LIKE谓词跨多个分区查询带有sparseGrams分词器的text索引时发生崩溃 (数据竞争) 。#109896 (groeneai)。 - 修复了在
LowCardinality(Nullable(...))列上构建minmax跳数索引时返回错误结果的问题:此前,下推到存储层的WHERE/PREWHERE/HAVING ... IS NULL谓词会裁剪掉所有 granule,导致即使该列包含 NULL 也返回 0 行。#110061 (groeneai)。 - 修复了当
prefer_localhost_replica选中本地副本时,Distributed表上的ORDER BY ... LIMIT查询执行缓慢的问题。#110136 (EmeraldShift)。 - 修复了
DELETE或ALTER UPDATE变更在WHERE条件的子查询中或UPDATE赋值中使用集合运算 (UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT) 时抛出异常 (UNION mode UNION_DEFAULT must be normalized) 的问题。#110196 (alexey-milovidov)。 - 修复了带有
x IN (subquery)的变更在主键分析期间构建子查询集合时,服务器关闭缓慢以及KILL MUTATION无响应的问题;现在集合构建会被及时取消。#110198 (alexey-milovidov)。 - 修复了
KILL TRANSACTION与在事务内执行的ALTER TABLE ... UPDATE/DELETE之间的竞态问题:如果回滚恰好发生在变更注册到事务之后、注册到表之前,就会遗留孤立的变更条目,进而在后台任务中引发逻辑错误 (Cannot find transaction ... that has started mutation ...) ,并阻塞受影响 parts 的所有后续变更,直至服务器重启。#110226 (tiandiwonder)。 - 修复了当
DataLakeCatalog(Iceberg/Glue) 数据库中某个表的元数据无法解析时,查询system.tables会导致整个查询中止或静默丢失表的问题。现在无论database_datalake_require_metadata_access如何设置,此类表仍会按名称列出,需要打开存储对象才能获取的列 (engine、total_rows等) 则返回默认值/NULL。直接访问损坏的表时仍会报错。#110242 (groeneai)。 - 连接顺序的基数估算现在基于经分区/主键裁剪后保留下来的 parts 汇总列统计信息,而非基于所有活跃 parts。此前,被裁剪到小分区的查询仍依据全表统计信息进行规划 (曾观察到行数被高估 2500 倍,导致哈希连接的构建端选反) ,而禁用统计信息反而能生成更优的计划。此外还修复了:JOIN 下的 MergeTree 关系中 lazy FINAL 被静默禁用的问题,原因是连接顺序优化器缓存的索引分析结果被误判为已应用的投影。#110283 (skuznetsov-clickhouse)。
- 在粒度不兼容 (一个为自适应、一个为非自适应) 的两个 MergeTree 表之间执行
ALTER TABLE ... MOVE/REPLACE PARTITION时,现在会抛出BAD_ARGUMENTS而非LOGICAL_ERROR。这种情况可由用户触发,因此不应作为内部错误抛出 (在 debug/sanitizer 构建版本中,内部错误会导致服务器中止) 。#110535 (groeneai)。 - 修复了
TTL ... DELETE WHERE <cond>的一个问题:若对WHERE中引用的列执行ALTER TABLE ... UPDATE后,某些行开始满足<cond>,这些行将永远不会被删除。现在该变更操作会重新计算行的生存时间 (TTL),新满足条件的过期行会被正常删除,而不再被静默保留。#110648 (groeneai)。 - 修复了
LOGICAL_ERROR“Invalid partition key size: 0” 错误:在启用non_replicated_deduplication_window的情况下,若某个异步插入批次仅被部分去重 (部分insert_deduplication_token重复,部分为新值) ,该错误可能导致向分区MergeTree表执行的INSERT中止。#110651 (groeneai)。 - 修复了新分析器下常量折叠会静默改变常量
Geometry值类型的问题。Geometry是一个具名Variant,其部分备选类型共享相同的存储布局 (LineString/Ring、MultiLineString/Polygon以及空值) ,因此仅备选类型不同的两个折叠常量会被合并为一个,例如常量MULTIPOLYGON EMPTY会变成LINESTRING()。#110709 (groeneai)。 - 修复了按序读取查询返回错误结果 (合并顺序错误) 的问题:当
distinct-in-order或aggregation-in-order将读取范围扩展到更长的排序键前缀,超出ORDER BY为按序读取虚拟行所设置的前缀时,就会出现该问题。虚拟行中多出的排序列被填充为默认值,可能导致MergingSortedTransform顺序错乱 (在 debug/sanitizer 构建中还会因LOGICAL_ERROR而中止) 。#110725 (groeneai)。 - 在使用服务器间密钥的集群上执行并行副本读取和 Distributed 读取时,现在会将查询的已启用角色 (SET ROLE / role=) 传递到远程节点;此前远程节点会回退为使用用户的默认角色,导致行策略的评估结果与发起服务器不一致。#110867 (evillique)。
- 修复了一个罕见的竞态问题:对
ReplicatedMergeTree表执行仅修改注释或仅修改设置的ALTER时,可能会静默丢弃由并发ALTER ... ADD COLUMN添加的列,导致某个副本停留在过时的表结构上。#111029 (tiandiwonder)。 - 修复了在封装
Distributed表的Merge表上执行带聚合的GROUP BY时出现的NUMBER_OF_COLUMNS_DOESNT_MATCH错误。该问题出现在分组键为某列的函数、且聚合函数读取同一列的情况下 (例如SELECT toString(g), min(g) FROM merge_over_distributed GROUP BY toString(g)) 。#111334 (groeneai)。 - 修复了在
Join引擎表 (StorageJoin) 上使用USING执行FULL JOIN时结果错误的问题:当左侧键为Nullable而存储键不是时,键为NULL的未匹配左侧行会返回0而非NULL。#111371 (groeneai)。 - 当表的
fsync_part_directory设置启用时,ALTER TABLE ... DETACH PARTITION/PART现在会对其在detached/下创建的克隆执行 fsync (包括数据分片子树以及直至磁盘根目录的整条目录链) ,Full (目录) 和 Packed 两种数据分片存储格式均适用。此前,用于将这些行从活动集合中移除的空覆盖数据分片会被 fsync,而克隆却从未被 fsync,因此若在确认后立即断电,btrfs 上已分离的数据可能会丢失 (未同步的克隆目录项会回滚,导致detached/为空,没有可供ATTACH的内容) 。该行为由现有的fsync_part_directory设置控制,默认行为保持不变。#111426 (groeneai)。 - 当表结构从存储推断时 (例如基于执行
SELECT NULL的视图创建的无列remote()/Remote/Distributed表) ,现在会在CREATE TABLE阶段直接拒绝Nullable(Nothing)(或任何其他不允许在表中使用的类型) 列,而不再持久化一份在下次服务器重启时无法加载、还会阻塞其他无关表加载的元数据。#111487 (groeneai)。 - 修复了使用并行副本读取时,若查询在发起端完全由投影优化 (精确计数、minmax 计数,或未选中任何范围的已存储聚合/普通投影) 给出结果,可能导致服务器中止的
LOGICAL_ERROR(Got read request from replica N for unknown stream ...) 。#111689 (groeneai)。 - 修复了 DeltaLake 分区
INSERT(allow_experimental_delta_lake_writes=1) 会损坏包含路径字符的分区值、且拒绝NULL的问题。此前,a/b这样的值会被静默提交为a,%会生成无法读回的数据文件,而NULL分区值会报NOT_IMPLEMENTED错误。现在,分区值会经百分号编码为单个路径段,真实值存储在partitionValues中,不再从路径中反向解析;NULL(或空字符串) 分区值则写为__HIVE_DEFAULT_PARTITION__,对应的partitionValues条目为 null。#111793 (groeneai)。 - 修复了在启用
enable_parallel_blocks_marshalling(默认启用) 的分片上执行分布式查询时出现的Expected UInt64 column for __grouping_set, got BLOB和ColumnBLOB should be converted to a regular column before usage逻辑错误,例如在包含本地副本的集群上执行GROUP BY GROUPING SETS,或读取同时涵盖本地表和分布式表的Merge表时。如果查询计划产生的块在同一进程内消费,则不再为其添加BlocksMarshallingStep。#111997 (groeneai)。 - 修复了
MergeTree表执行变更时出现的LOGICAL_ERROR(Type mismatch when building statistics for column) ,该问题发生在某列带有统计信息、且其类型已通过仅修改元数据的ALTER MODIFY COLUMN更改 (例如Enum8改为Int8,或DateTime改为UInt32) 的情况下。现在,变更只会重新计算其实际重写的列的统计信息,其余统计信息原样保留;对于由MATERIALIZE COLUMN、由对某个MATERIALIZED列所依赖列执行的UPDATE,或由CLEAR COLUMN重写的列,现在会重新计算其统计信息,而不再保留过时的内容。#112009 (groeneai)。 - 修复了当查询按
intDiv(constant, key)或divide(constant, key)过滤时会静默遗漏行的问题。对于常量除以键列的情况,主键和分区分析给出了错误的单调性方向,导致本应匹配的粒度被剪枝,查询在没有任何报错的情况下返回了更少的行。同时修复了无符号常量被除数最高位为 1 时intDiv的问题;当Decimal操作数导致除法以该 decimal 的原生位宽计算时,不再声明单调性;此外,对于将IPv4/IPv6常量除以键列的合法查询,键分析不再抛出Cannot compare DB::IPv4 with long。#112156 (groeneai)。 - 修复了参数化视图在
SELECT主体中使用INTERSECT/EXCEPT,或使用混合了UNION DISTINCT与UNION ALL的UNION链时,被错误归类为普通视图的问题。此类视图可以成功创建,但其元数据无法读回:加载时会抛出Invalid storage definition in metadata file,导致该视图永远无法加载,并使 debug 或 sanitizer 构建的服务器在启动时中止。此外,system.tables.parameterized_view_parameters也不会为这些视图报告任何参数。#112211 (groeneai)。 - 修复了查询在计算
geohashesInBox时max_execution_time和KILL QUERY被忽略的问题。此类查询会先展开数据块中的每一行才能被中断,因此取消操作要数分钟后才生效;现在该函数会在遍历行的过程中检查查询的时间限制。在持久化的表表达式 (例如排序键、跳数索引或PARTITION BY) 中进行的计算不在本次修复范围内,将另行跟进。#112273 (groeneai)。 - 修复了在 Merge 表上使用 PREWHERE 时出现的逻辑错误,该 Merge 表的底层为另一个 Merge 表或列类型不同的 materialized view。同时修复了在从远程服务器读取数据的表 (Distributed 表,或封装了 Distributed 表的表) 上行策略被静默忽略的问题,该问题可能导致本应被策略隐藏的行暴露出来;此类查询现在会以 ILLEGAL_PREWHERE 错误被拒绝。请改为在每台远程服务器的底层本地表上定义这些策略;注意,对于通过
serialize_query_plan = 1下发的读取,此类策略仍不会生效,这是一个独立的、早已存在的 bug。#112326 (PedroTadim)。 - 修复了
ALTER TABLE ... MODIFY COLUMN修改类型后,若对应的变更从未执行 (例如被KILL MUTATION移除) ,会读取到过期二级 (跳数) 索引的问题:磁盘上的粒度按旧类型写入,却按新类型解码,从而引发LOGICAL_ERROR、申请高达数 EB 的内存分配,或静默返回错误结果。同时修复了基于表达式的索引在表达式语义改变而存储字节完全不变 (因而根本不会创建变更) 时返回错误结果的问题,例如仅修改DateTime时区,或仅修改自定义类型名称 (如将UInt8改为Bool) 的MODIFY COLUMN。现在对于受影响的数据分片,此类索引会被跳过。#112484 (groeneai)。 - 修复了在集群上执行聚合的查询在启用
serialize_query_plan = 1和基于计划的并行副本时出现的LOGICAL_ERROR(Cannot add transform Resize to Pipes because it has no outputs) ,其原因是合并步骤将管道调整为零个流。#112506 (groeneai)。 - 修复了
ReplicatedMergeTree副本在应用自身待处理的ALTER ... ADD COLUMN之前,对从其他副本拉取的数据分片执行变更时出现的LOGICAL_ERROR(“Part … contains column … that is absent in table …”) 。现在此类变更会推迟到元数据变更应用之后再执行。#112510 (groeneai)。 - 修复了当查询的
ORDER BY落盘时,读取计数器 (read_rows、read_bytes、ProfileEvents['SelectedRows']、ProfileEvents['SelectedBytes']) 以及READ_ROWS和READ_BYTES配额被多计的问题。从外部排序临时 File 中重新读取的行会再次被计为源端读取,导致发生落盘的查询多报读取量,即使并未超出配额,也可能因QUOTA_EXCEEDED而被拒绝。#112645 (groeneai)。 - 修复了
ProfileEvents['JoinResultRowCount']少报落盘JOIN结果大小的问题。从延迟桶中输出的行仅计入了JoinDelayedJoinedTransformRowCount,而未计入总数。查询结果始终正确,仅该 profile 事件有误。#112673 (groeneai)。 - 修复了分布式查询在与副本建立连接期间,
max_execution_time和KILL QUERY静默失效的问题。此类查询现在会在下一次尝试连接时停止,而不会再逐一尝试所有剩余副本并重试。#112689 (groeneai)。 - 修复了在未完成的
RENAME COLUMNalter 变更仍在进行时,MergeTree表上的ALTER仍会被应用的问题。该问题可能导致存储元数据被以不兼容的方式更新,并使后续变更被完全阻塞。#112783 (Michicosun)。 - 修复了从基于
Distributed表的Merge表读取时ORDER BY结果错误的问题:返回的行可能顺序错乱,并且在使用LIMIT时,本应出现在结果中的行可能缺失。#112931 (alexey-milovidov)。 - 修复了在启用
share_nested_offsets(默认启用) 的表上,当启用文件系统读取预取,且Nested列与某个曾被删除后又重新添加的子列一同读取时结果错误的问题。此类查询可能会为某个物理上存在、且从未被ALTER改动过的列返回默认值。在对象存储上,由于remote_filesystem_read_prefetch默认为1,无需任何非默认设置即可触发该问题;在本地磁盘上则需设置local_filesystem_read_prefetch = 1。另有一个与预取无关的独立缺陷,在读取范围跨越多个块时仍会导致此类读取结果损坏,该问题不在本次修复范围内。#112997 (groeneai)。 - 修复了按分区分发数据的查询 (例如带
PARTITION BY的窗口函数,或使用join_algorithm = 'parallel_full_sorting_merge'的连接) 中,当某个分片的下游已结束、而某个块仅分发了一部分时出现的Pipeline stuck逻辑错误。#113190 (groeneai)。 - 修复了在
ReplicatedMergeTree上以alter_sync = 2执行ALTER、OPTIMIZE、TRUNCATE及分区操作语句时,如果表在语句等待其他副本期间开始关闭 (例如因并发执行DROP DATABASE ... SYNC) ,语句会挂起的问题。此类语句现在会以UNFINISHED报错失败,并且同样遵循max_execution_time和KILL QUERY。#113228 (groeneai)。 - 修复了在启用
read_in_order_use_virtual_row时,若MergeTree按序读取查询同时使用WITH FILL ... INTERPOLATE和IN或has过滤条件,会出现Cannot insert element into Set(NOT_IMPLEMENTED) 错误的问题。#113264 (groeneai)。 - 修复了在启用设置
inject_random_order_for_select_without_order_by且聚合查询从包含Distributed子表的Merge表读取数据时出现的逻辑错误 (异常)Chunk info was not set for chunk in MergingAggregatedTransform:对于仅规划到中间阶段的查询,不再注入随机的ORDER BY rand()包装。#113266 (alexey-milovidov). - 修复了当
MergeTree表包含两条或更多时间表达式完全相同、仅WHERE条件不同的TTL ... DELETE WHERE规则时,行永远不会被删除的问题。执行一次 TTL 删除合并后,该数据分片的rows_where_ttl_info会被重置为零,导致此后再也不会为其调度 TTL 合并,过期行因此被无限期保留,且不会产生任何错误或日志信息。#113384 (groeneai). - 修复了当查询在表元数据中存储的表达式 (例如 sorting key、跳过索引或
PARTITION BY键) 内计算geohashesInBox、arrayFold、sleep、base58Decode、h3PolygonToCells或h3PolygonToCellsWithContainment时,max_execution_time和KILL QUERY不生效的问题。#113456 (groeneai). - 修复了当包含多个子表的
Merge表读取外层查询所引用的 materialized CTE 时抛出的LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) 。#113558 (alexey-milovidov). - 修复了对包含多个子表、带有纯列
PREWHERE以及单独WHERE的Merge表执行EXPLAIN ANALYZE时出现的Logical error: 'Required output position N is out of range for pass-through inputs'。#113725 (groeneai). - 修复了当视图的列类型与底层存储不同 (例如基于
system.tables的information_schema.tables,前者的engine为Nullable(String),后者为String) 时,将该视图上的过滤条件下推到存储所引发的逻辑错误 (Unexpected return type) 。#113984 (alexey-milovidov). - 修复了谓词包含
IN (subquery)的变更在子查询的集合仍在构建时被取消 (例如通过KILL MUTATION或DETACH DATABASE) 所出现的Not-ready Set is passed as the second argument for function 'in'错误。#114463 (groeneai). - 对用于排序键、主键或分区键的列执行
ALTER TABLE ... DROP COLUMN时,现在会与ALTER TABLE ... CLEAR COLUMN一样,以ALTER_OF_COLUMN_IS_FORBIDDEN报错并给出说明。此前,该操作会在重新计算键表达式时报出令人困惑的UNKNOWN_IDENTIFIER: Missing columns错误。当Nested组中的某列被用于键时,按公共前缀删除或清空整个组同样适用此规则;此前这种操作可能会静默破坏该组的数据,或留下一个永远无法完成的变更。删除仅在TTL表达式中使用的列时,现在也会报告该操作会破坏哪个 TTL 表达式 #114468 (m7kss1). - 修复了在同一个
ALTER中被重命名、删除后又重新添加的列,在变更尚未完成时返回已删除列的值、而非其自身默认值的问题。#114601 (tiandiwonder). - 修复了当底层表将父列声明为
ALIAS时,通过Merge表读取子列 (.size0、.null、元组元素、String.size) 的问题。此前此类读取会返回该类型的默认值;若同一查询中还选择了父列,则可能返回某个无关列的值。#114673 (groeneai)。 - 修复了当多边形参数为无效的常量字面量且
validate_polygons = 0时,基于 MergeTree 主键使用pointInPolygon过滤的SELECT结果中缺失行的问题。此前主键分析会基于一个从未校验过的多边形进行粒度剪枝,从而误删包含匹配行的粒度。#114710 (groeneai)。 - 修复了
ALTER TABLE ... MATERIALIZE INDEX、MATERIALIZE STATISTICS和MATERIALIZE PROJECTION的格式化问题:格式化时会丢失IF EXISTS子句,导致格式化后的查询与原先解析的查询不一致。此外,现在会拒绝四种ALTER ... STATISTICSAST JSON 负载,这些负载无法由 SQL 解析器生成,且格式化后会变成另一条命令。#115099 (groeneai)。 - 修复了对
LowCardinality(String)键进行聚合或 JOIN 时,若其字典在聚合过程中不断增长,会越界读取缓存的字典哈希的问题,该问题可通过TTL ... GROUP BY触发。此问题可能导致哈希值错误,并在 sanitizer 构建中报告 heap-buffer-overflow。#115604 (groeneai)。 CREATE TABLE和ALTER TABLE现在禁止在分区键所用的列上使用有损编解码器 (如SZ3) 。#115626 (groeneai)。- 通过
Merge表读取时,若匹配到的Alias表指向参数化视图,将不再抛出LOGICAL_ERROR: Table has no columns.(该错误在 debug 和 sanitizer 构建中会导致服务器中止) 。此类表现在会报告STORAGE_REQUIRES_PARAMETER,与参数化视图自身报告的错误一致。其他任何无法提供列的匹配表现在会报告UNSUPPORTED_METHOD,而非内部错误。#115896 (groeneai)。 - 修复了表达式引用
_sample_factor的待处理变更在即时预览时的问题。在apply_mutations_on_fly = 1且带有SAMPLE子句时,该表达式此前会使用读取查询的样本系数求值,而非后台物化时持久化的值,导致预览的行与最终物化结果不一致;此外,一个待处理的ALTER TABLE t DELETE WHERE _sample_factor > 1可能导致SAMPLE读取不返回任何行。查询自身的_sample_factor列不受影响。#115906 (groeneai)。 - 格式版本为
V3的统计信息文件现在可以正常读取,不再因ILLEGAL_STATISTICS被拒绝。此类文件仅由某一短暂时间段内的master构建生成,但包含这些文件的数据分片将完全无法读取,而在只读磁盘上也无法通过ALTER TABLE ... MATERIALIZE STATISTICS重新生成。#116030 (alexey-milovidov)。 - 修复了
SELECT ... FROM t STREAM ... ORDER BY ... LIMIT n查询读取带有PROJECTION的表时报错Invalid number of columns in chunk pushed to OutputPort(LOGICAL_ERROR) 的问题。STREAM读取不再应用延迟物化。#116187 (groeneai)。 - 对于 Replicated 数据库,不再复制
ALTER TABLE ATTACH PARTITION FROM。#94835 (MikhailBurdukov)。 - 修复了当已回滚的事务性 MergeTree 数据分片与已提交的数据分片相交时,表启动期间出现服务器中止 (在 sanitizer 构建版本中) 以及静默数据丢失的问题。
PartLoadingTree::add现在能够正确识别两个相交数据分片中哪一个已被回滚,将其移除,并按正确顺序把其遗留的子分片重新挂到已提交的数据分片下。#100992 (tuanpach)。 - 修复了
indexOfAssumeSorted在 MergeTree 表中处理Array(LowCardinality(String))列时返回错误结果的问题。#101771 (Onyx2406)。 - 修复了读取
Iceberg或DeltaLake数据湖表时出现的LOGICAL_ERROR异常。该问题发生在读取路径未固定datalake_table_state即进入读取管道的情况下,例如并发的Iceberg元数据更新,或对DeltaLake表执行的merge读取。#102033 (groeneai)。 - 修复了在分区键为
Time类型的表上,OPTIMIZE TABLE ... PARTITION ...(以及其他通过convertFieldToTypeImpl解析分区值的查询) 抛出Logical error: Parsed partition value: ... doesn't match partition value for an existing part with the same partition ID: ...的问题。#106202 (groeneai)。 - 修复了轻量级删除后未留下投影分片时,数据分片被错误标记为投影已损坏的问题。这种情况可能发生在投影重建后输出行数为零,或投影被删除时 (
lightweight_mutation_projection_mode = 'rebuild'/'drop') 。此前,该损坏状态会导致针对该数据分片的查询无法使用投影优化。#106273 (tiandiwonder)。 - 修复了
system.warnings中的内存/CPU/变更过载警告比异步指标滞后一个周期 (且在首个周期中缺失) 的问题。#108035 (alexey-milovidov)。 - 修复了在启用实验性设置
make_distributed_plan = 1时,查询基于Distributed表或视图的Merge表会出现LOGICAL_ERROR异常 (ScatterExchangeStep should have one source shard, got 8) 以及重复行的问题。#108401 (groeneai)。 - 修复了当
Nullable(Tuple(...))列中的非 NullableLowCardinality元素被用作子列 (例如用作排序键) 时,合并期间服务器中止 (Sort order of blocks violated) 以及读取结果错误的问题。#108679 (groeneai)。 - 修复了当账户密钥不是有效的 Base64 时,经由
azureBlobStorage()(以及相关的 Azure 表函数/存储) 调用内置 Azure SDK 的Base64Decode导致崩溃的问题。>= 0x80的字节会导致解码表越界读取,而任何无效字节都会导致对负值执行未定义的左移操作 (在 sanitizer 下会中止) 。现在无效密钥会被正常拒绝。#108716 (groeneai)。 - 修复了一个
LOGICAL_ERROR(“New empty part is about to materialize but the directory already exist”) :如果 MergeTree 表上的前一次DROP/DETACH/MOVE/REPLACE PARTITION操作被中断 (例如事务回滚或崩溃) ,并遗留了过期的tmp_empty_<part>目录,那么再次执行此类操作时,可能会导致调试和 sanitizer 构建版本中的服务器中止。现在会直接回收该过期目录,不再报错。#108879 (groeneai)。 - 修复了 wide part 中列的
TTL过期后,projection 返回该列类型的默认值 (例如0) ,而非其 DDL 中定义的DEFAULT值 (例如-1) 的问题。#109013 (tiandiwonder)。 - 修复了使用自定义
disk设置 (SETTINGS disk = disk(...)) 创建的MergeTree表执行ALTER查询失败的问题。#109199 (Michicosun)。 - 修复了通过
Merge表读取MaterializedPostgreSQL数据库中的表时,会读到过期行和已删除行的问题。#109339 (vdimir)。 - 修复了读取按
BIGINT列分区、且分区值超出Int32范围的 Paimon 表时出错的问题。此前此类分区值会被截断 (例如9223372036854775807变为-1) ,导致生成错误的分区路径,并因文件系统错误而失败。#109510 (groeneai)。 - 修复了从
Merge表读取数据时,若其子表的行策略过滤器仅为一个已存在的列 (例如CREATE ROW POLICY ... USING flag) ,会出现逻辑错误 (“Cannot determine row level filter; 0 columns deleted, 0 columns added”) 的问题。#109843 (groeneai)。 - 修复了 IcebergLocal 错误地将存储类型报告为 Azure 的问题。#109872 (PedroTadim)。
- 对于元数据加载失败的 projection part,
CHECK TABLE现在会报告实际的损坏情况,而不再报告具有误导性的Columns doesn't match ... Expected: 0 columns错误。#110262 (Algunenano)。 - 修复了对象存储磁盘上的
MergeTree表在残留的txn_version.txt.tmp文件磁盘级元数据损坏时,导致服务器启动失败的问题。#110519 (alexey-milovidov)。 - 修复了带有
_part_offset或提交顺序 projection 的 MergeTree 表,在禁用allow_part_offset_column_in_projections或allow_commit_order_projection后,一旦表被分离或服务器重启,便永久无法重新附加的问题。这两个设置仅在 CREATE 时进行校验,因此 ATTACH 时不再重新检查。#110570 (groeneai)。 - 修复了一个罕见的
LOGICAL_ERROR(“Unexpected number of parts to remove from parts_queue”) :在ReplicatedMergeTree上,当两个分区操作 (例如两个MOVE PARTITION/REPLACE PARTITION查询,或其中一个与后台DROP_RANGE发生竞争) 同时取消重叠范围内的后台 part 检查时,可能导致服务器异常终止。#110738 (groeneai)。 - 修复了使用
Quantized(...)编解码器的列嵌套在可池化的序列化中时,可能出现的Hash is not set for serialization逻辑错误。典型场景如:基于多个源表创建的Merge表中,同名列类型不同 (被合并为Variant) 。#110776 (groeneai)。 - 修复了当
max_streams_for_merge_tree_reading取极端值 (接近UInt64最大值) 且同时设置allow_asynchronous_read_from_io_pool_for_merge_tree = 1时,读取 MergeTree 表出现std::length_error(LOGICAL_ERROR) 的问题。现在该设置的上限会被限制为与max_threads相同。#110936 (groeneai)。 - 修复了对单列
MergeTree表执行合并时出现的逻辑错误Cannot calculate columns sizes when columns or checksums are not initialized。该问题出现在表中唯一的列带有会完全过期的列级TTL(且min_bytes_for_wide_part = 1) 时。#111169 (groeneai)。 - 当设置了
min_rows_to_fsync_after_merge/min_compressed_bytes_to_fsync_after_merge/fsync_part_directory时,现在会对合并或物化后 part 中的文本索引文件执行 fsync。此前,这些文件是 part 中唯一未同步的文件,因此合并后若立即断电,可能会留下一个已提交但已损坏的 part,进而导致数据丢失。#111335 (groeneai)。 - 修复了当清单中的分区 Tuple 与其分区规范不匹配时,
Iceberg表上OPTIMIZE TABLE ... MANIFEST出错的问题 #111368 (SmitaRKulkarni)。 - 修复了以下问题:当“直接从文本索引读取”优化在具有多个
text索引的MergeTree表的读取头中遗留未使用的索引虚拟列时,延迟物化优化会出现越界读取 (发行版) / 逻辑错误 (debug 构建版本) ,同时Merge表的Pipe::unitePipes中也会出现逻辑错误。#111467 (groeneai)。 - 修复了在调低
part_minmax_index_columns(例如从with_block_number_offset改回partition_key_only) 后,debug/sanitizer 构建中可能导致后台合并中止的LOGICAL_ERROR(“Part level Min-Max index was constructed from unexpected columns set”) 。#111511 (groeneai)。 - 修复了对包含多个分区且定义了行策略的表执行
STREAM读取 (enable_streaming_queries = 1) 时发生的崩溃。在 debug 和 sanitizer 构建中,会因逻辑错误Filter column ... not found in DAG outputs而失败;在发行版构建中则可能发生段错误。#111572 (groeneai)。 - 修复了
MergeTree表在当前设置禁用多态 parts (非自适应粒度) 的情况下加载已有Compactpart 时抛出的LOGICAL_ERROR(Cannot create part with type Compact and storage type Full because table does not support polymorphic parts) 。例如,当只读表与另一个表共享磁盘路径,并通过SYSTEM RESTART DISK或在服务器启动时重新加载其 parts 时,就可能出现这种情况。在 debug 和 sanitizer 构建中,该异常会导致服务器中止。#111626 (groeneai)。 - 当
fsync_part_directory = 1时,将 part 目录从临时名称重命名为最终名称的操作现在也会通过对父目录执行 fsync 来保证持久性 (对于跨父目录的移动,还会同步源父目录) 。此前只会对被移动的目录执行 fsync,因此若在 part 提交后立即断电,即使其文件已写入,磁盘上也可能缺失该 part,导致在启用该设置的情况下仍然丢失行。#111861 (groeneai)。 - 修复了从
MergeTree表中同时选择Nullable(Tuple(...))列及其某个携带空值的元素子列 (Variant、Dynamic或LowCardinality) 时出现的错误结果和LOGICAL_ERROR。读取该子列时,会将父 tuple 中为NULL的行,在一个已通过子流缓存共享的列中标记为NULL,导致读取整列时得到错位的值。#111949 (groeneai)。 - 修复了在配置了自动溢写到磁盘阈值时 (自 26.5 起为默认配置) ,哈希连接会丢失构建后优化 (转换为固定哈希表、共享运行时过滤器、右表范围重排) 的问题。#111972 (alexey-milovidov)。
- 修复了在未使用
simdcomp的构建 (除 x86_64 Linux 之外的所有目标平台,例如 aarch64) 上,当text_index_posting_list_apply_mode = 'lazy'时,hasAllTokens及其他多标记text索引搜索返回错误结果 (静默丢失行) 的问题。可移植的位打包解码器在块的位宽为零时不会写入解码后的零值,导致位于单条倒排记录段中的倒排记录被丢弃。磁盘格式保持不变,修复后现有数据可正常读取。#112178 (groeneai)。 - 加载损坏的 MergeTree 统计信息时,相关操作现在会直接失败,而不再忽略该错误。#112201 (skuznetsov-clickhouse)。
- 修复了 HDFS 上已确认的 Iceberg 写入被静默丢失的问题:Iceberg 提交会通过条件写入来发布每个新的元数据文件,但
HDFSObjectStorage忽略了该条件,直接执行普通覆盖写入,导致所有并发写入方都收到了确认,而其中一个写入方的快照却变得不可访问。现在 HDFS 会拒绝条件写入,因此 HDFS 上由存储管理的 Iceberg 写入 (包括带有显式列列表的CREATE TABLE ... ENGINE = IcebergHDFS(...)) 将会失败。读取不受影响。#112437 (groeneai)。 - 修复了对
KeeperMap表执行DELETE时仅删除前max_block_size条匹配行,却将该变更报告为成功完成的问题。同时修复了在keeper_map_strict_mode = 1时DELETE不具备原子性的问题:它可能回退为无版本删除,从而误删被并发更新的行;而且它会逐块应用匹配的行,一旦发生冲突,删除操作可能只被部分应用。#112777 (alexey-milovidov)。 - 修复了读取或合并路径上的瞬时 Azure Blob 存储错误 (RBAC 权限传播导致的
403 Forbidden、凭据身份验证失败,或以408形式出现的连接超时) 被误判为不可重试并报告为POTENTIALLY_BROKEN_DATA_PART(Code 740) ,从而针对健康的数据分区触发严重告警误报的问题。这些瞬时故障现在会被视为可重试;而真正持续存在的故障会以普通 Azure 错误的形式报告,不再被误报为损坏的数据分区。#112871 (arsenmuk)。 - 修复了在带前缀端点的 Azure Blob 存储磁盘上,
listObjects从第二页起每页都返回错误 blob 名称的问题,原因是分页绕过了负责去除端点前缀的客户端包装器。现在分页会通过续传令牌重新进入该包装器,确保每一页的 blob 名称均正确。#112872 (arsenmuk)。 - 修复了当数据分区由不重写整个分区的变更生成时,基于
_block_number和_block_offset的分区级 minmax 索引会在表重新加载后丢失的问题。#112878 (alexey-milovidov)。 - 修复了当变更谓词使用
merge表函数且未显式指定数据库名称时引发异常的问题 (在发布构建中表现为导致服务器无法启动的错误) 。现在会使用被变更表所在的数据库,与表名的处理方式一致。#113185 (alexey-milovidov)。 - 修复了在启用
share_nested_offsets = 1的MergeTree表上,将删除后又重新添加的Nested成员的子列与同组中现存成员一同读取时,返回错误结果并触发LOGICAL_ERROR的问题。只要读取跨越多个块,现存成员就会返回来自后续块的值。#113225 (groeneai)。 - 修复了在 debug 和 sanitizer 构建中,当
max_streams_to_max_threads_ratio设置得非常大时读取Merge表出现的算术异常:流的数量被截断为 32 位,导致2^32的倍数变为零。此外,当Merge表的流数量相乘结果超出size_t时,现在会抛出PARAMETER_OUT_OF_BOUND,而不再引发未定义行为;按数据量限制MergeTree流数量时不再发生溢出;聚合源数量超过 65536 的Merge表读取请求将被拒绝。#113382 (alexey-milovidov)。 - 修复了向
hdfs磁盘写入失败的问题:写入会报错Parent directory doesn't exist,原因是生成的对象键包含嵌套的目录前缀,而 HDFS 与 blob 存储不同,具有真实的目录,且在创建文件时不会自动创建缺失的父目录。#113396 (alexey-milovidov)。 - 修复了向
remote/remoteSecure表函数或Remote/RemoteSecure表引擎传入不存在的命名集合并同时附带key = value覆盖参数时报错信息不正确的问题。此类调用会被静默地重新解析为位置参数调用,导致覆盖参数被当作数据表达式分析,报告的错误也与实际问题毫不相干 (例如对于remote(collection, database = merge(...))会报告 Function with namemergedoes not exist) 。现在会正确报告命名集合不存在。#113510 (groeneai)。 - 修复了当
merge_max_block_size_bytes设置得小于空列的byteSize()时,后台合并和OPTIMIZE陷入无限循环的问题。空的LowCardinality列仍带有字典,因此可能在合并任何一行之前就已达到字节上限;此后合并会无休止地生成空块,持续占满一个 CPU 核心,且始终不释放其后台池槽位。#113585 (groeneai)。 - 修复了当表使用
serialization_info_version = 'basic'时,对 Compact part 执行变更的结果会因该 part 的序列化信息仍在内存中还是已从serialization.json重新加载而有所不同的问题。在ReplicatedMergeTree上,这会导致持有字节完全相同的源 part 的两个副本写出不同的变更后 part,进而使变更因CHECKSUM_DOESNT_MATCH而失败。#113588 (groeneai)。 - 当目标存储无法读取 .lock 文件时,备份现在会报告底层的锁文件访问错误,而不再误报存在并发备份。#113637 (kirillshokhin)。
- 修复了
MergeTree表的后台任务 (统计信息刷新、parts 刷新、过期/意外 parts 加载) 与表销毁之间的数据竞争。#113722 (alexey-milovidov)。 - 修复了当被更新表所在的数据库与会话的数据库不同时,
UPDATE和轻量级删除读取错误表的问题。现在,变更的表达式会基于被更新表所在的数据库进行规范化,既包括隐式使用当前数据库的merge表函数,也包括未限定的表标识符。此前,这些名称会基于会话的数据库解析,导致语句在无任何提示的情况下更新或删除了从另一张表中选出的行。#113748 (groeneai)。 - 修复了按主键范围 layer 读取
MergeTree表时,若某个 layer 产生空 pipe 会抛出异常的问题。#114177 (alexey-milovidov)。 BACKUP、RESTORE和ENGINE = Backup现在会依据用户的SOURCES授权对备份位置进行鉴权,与s3()、file()和azureBlobStorage()的做法一致。此前,拥有BACKUP权限但没有SOURCES权限的用户可以向服务器可访问的任意位置写入备份,也可以从任意此类位置读取备份。现在,写入备份需要对目标端对应的数据源拥有WRITE权限 (WRITE ON S3、WRITE ON AZURE、WRITE ON FILE) ,读取备份则需要READ权限;Disk(...)目标端仍仅受backups.allowed_disk限制。#114405 (groeneai)。- 修复了在变更执行期间读取表时的问题:
MATERIALIZED列可能返回过期的值,且与已更新的列一同查询时可能报错。#114561 (tiandiwonder)。 - 修复了启用
make_distributed_plan时,读取子表包含内部集合运算的Merge表会出现逻辑错误 (Block structure mismatch) 的问题。#114753 (alexey-milovidov)。 - 对于引擎未实现合并整理的对象存储表,
OPTIMIZE TABLE此前实际未执行任何操作,却报告成功。现在会抛出错误,与其他不支持该语句的引擎行为一致。此变更影响DeltaLake、Paimon、Hudi以及普通对象存储引擎 (S3、GCS、COSN、OSS、AzureBlobStorage、HDFS以及基于对象存储的URL) ;已实现合并整理的Iceberg不受影响。#114805 (groeneai)。 - 修复了在启用
allow_deprecated_syntax_for_merge_tree时,使用已弃用的位置参数语法创建的ReplicatedMergeTree表出现BAD_DATA_PART_NAME(“Trying to get part name in new format for old format version”) 的问题。此前,变更可能在尚未应用它的副本上被报告为已完成,且表在重启后可能一直处于只读状态。#114980 (groeneai)。 - 修复了使用轻量级更新的表上出现
Found patch part ... that intersects mutation with version ...(LOGICAL_ERROR) 的问题。合并补丁分区片段时,可能生成一个数据版本范围跨越某个现有分区片段数据版本的补丁;该补丁既无法应用也无法跳过,导致该分区上后续所有操作均失败,复制队列也随之停滞。现在不会再分配此类合并任务。#115064 (alexey-milovidov)。 - 修复了
Backup数据库引擎引用的备份变得不可用时 (例如其文件已被删除或底层存储无法访问) ,服务器无法启动的问题。现在该数据库会以不含任何表的形式加载,而不会导致整个服务器无法启动。#83188 (orloffv)。 - 修复了磁盘写满错误后日志无法恢复的问题。此前,日志磁盘写满时,ClickHouse 会进入失败状态,并持续向 syslog 刷屏写入错误消息 (可能高达每小时 100 GB 以上) ,即使磁盘空间释放后也无法恢复。现在,一旦磁盘空间可用,日志系统即会自动恢复,无需重启服务器。#93127 (jaehanbyun)。
- 修复了 DeltaLake 存储中 schema visitor 导致崩溃的问题。#97112 (kssenii)。
数据湖与外部存储相关修复
- 修复了 S3 分段上传 (例如
INSERT INTO ... hits_s3) 时偶发的Code: 499 ... InvalidPart(S3_ERROR) 失败问题。MinIO 在执行CompleteMultipartUpload时,可能会短暂地将刚上传的分片报告为缺失;现在该错误会与已处理的NoSuchKey一样进行重试,重试次数上限由s3_max_unexpected_write_error_retries控制。#109364 (groeneai)。 - 对于数据文件格式不是
Parquet的 Iceberg 表,ALTER TABLE ... DELETE和ALTER TABLE ... UPDATE现在会直接被拒绝并返回明确的NOT_IMPLEMENTED错误,而不再导致服务器崩溃或静默损坏表。#105893 (groeneai)。 - 修复了从
file、s3或input等表函数执行INSERT SELECT时,若多次选择同一源列,会报错Cannot add column ...: column with this name already exists的问题。#105982 (crakjie)。 - 通过 HTTP 查询字符串参数传递的敏感值 (例如
param_secret_key/param_aws_secret_access_key等param_*查询参数绑定、password参数或 S3 风格的signature参数) 不再以明文形式写入system.text_log或 OpenTelemetry span。Request URI日志行现在会对名称疑似敏感的参数值进行脱敏,将其替换为[HIDDEN]。#108475 (groeneai)。 - 修复了
S3Queue和AzureQueue表引擎的_etag虚拟列问题:该列虽已声明,但从未被填充,导致SELECT _etag始终返回空字符串。现在它会返回对象的 ETag,行为与S3引擎和s3()表函数一致。#108625 (groeneai)。 - 读写 S3 的查询如果在 S3 请求尚未完成时被取消 (例如通过
KILL QUERY) ,现在会正确报告为已取消,而不再报告具有误导性的网络/S3 错误。具体而言,向 S3 执行的备份或恢复操作被取消时,system.backups中现在会显示BACKUP_CANCELLED/RESTORE_CANCELLED。#108673 (jkartseva)。 - 修复了
S3Queue表引擎的_tags虚拟列问题:该列虽已声明,但从未被填充,导致SELECT _tags始终返回空 map。现在它会返回对象标签,行为与S3引擎和s3()表函数一致。#108676 (groeneai)。 - 修复了在数据湖目录数据库中,SHOW TABLES 与 SELECT … FROM system.tables 返回结果不一致的问题:ClickHouse 无法读取的表现在会在两者中统一隐藏。#109273 (SmitaRKulkarni)。
- 修复了向 Delta Lake 表 (
DeltaLakeLocal/deltaLake) 执行INSERT时,如果在 sink 已开始写入后发生失败 (例如源查询在插入过程中抛出异常,或查询被取消) ,会导致服务器中止 (在发布构建中则会导致数据文件被静默地遗留为未完成状态) 的问题。#109328 (groeneai)。 - 修复了在
optimize_functions_to_subcolumns=1(默认值) 时,对经过 schema 演进、在旧数据文件写入之后才新增的 Iceberg 列执行WHERE col IS NULL/IS NOT NULL,会报错Not found column or subcolumn c.null in block(在 debug/sanitizer 构建中则报错Bad cast from ColumnConst to ColumnNullable) 的问题。#109515 (groeneai)。 - 修复在
CREATE TABLE ... AS SELECT查询中,将标量子查询用作s3表函数的 URL 参数 (或任何其他表函数的参数) 时出现的Host is empty in S3 URI错误:表函数参数中的标量子查询现在会在查询分析阶段求值。#110254 (CheSema)。 - 修复在 Iceberg 表上执行多命令
ALTER(例如UPDATE ..., DELETE ...) 时出现的逻辑错误 (在 debug/sanitizer 构建中会导致服务器中止) 。此类变更现在会被拒绝,并返回明确的NOT_IMPLEMENTED错误。#110347 (groeneai)。 - 修复当初始 schema 包含嵌套字段 (
Tuple/Array/Map) 时,Iceberg 表在执行ALTER TABLE ... ADD COLUMN后产生重复字段 ID 的问题。last-column-id现在会记录包括嵌套子字段在内的最大已分配字段 ID,因此后续添加的列不会再复用嵌套字段的 ID,读取时也不会再因ICEBERG_SPECIFICATION_VIOLATION(Duplicate field id) 而失败。#110884 (groeneai)。 - 修复当 Iceberg 表同时包含在
ALTER TABLE ... ADD COLUMN之前和之后写入的数据文件,且启用了optimize_move_to_prewhere时,对该表执行DELETE/UPDATE会静默删除错误的行 (或抛出NOT_FOUND_COLUMN_IN_BLOCK) 的问题。#111693 (groeneai)。 - 修复在 Iceberg 表上执行
ALTER TABLE ... EXECUTE expire_snapshots后,system.iceberg_history中被保留快照的made_current_at变为1970-01-01的问题。同时修复当表的元数据中没有snapshot-log时,system.iceberg_history不返回任何行的问题。#111781 (groeneai)。 - 修复通过
MATERIALIZED VIEW向 Iceberg 表插入数据时出现的数据损坏问题。此前数据文件是按照目标表在CREATE时的列类型写入的,而非其当前实际的 Iceberg schema,导致DateTime值被存储为裸 Avroint,读回时又被解释为微秒;若使用DateTime64(0)或DateTime64(9),文件则完全无法读回。因此,当目标表的 Iceberg schema 比视图声明的列更宽时,INSERT INTO <materialized view>现在会抛出TYPE_MISMATCH,而不会写入损坏的行。#112359 (groeneai)。 - 修复写入 schema 中包含嵌套元组 (元组内嵌元组) 的 Iceberg 表时出现的问题。此前发布的表元数据会将内层元组的字段名替换为位置名称
1、2……,导致使用默认的Parquet格式时INSERT因INCORRECT_DATA而失败,使用Avro时则无法读回该列。#112480 (groeneai)。 - 修复两个查询同时解析同一表名时,导致
Filesystem或HDFS数据库永久卡死的死锁问题。此前该数据库上的所有后续查询都会无限期阻塞且无法中断,只能重启服务器才能恢复。#112495 (groeneai)。 - 修复当
WHERE谓词中NOT之下含有 delta-kernel 谓词转换器无法处理的子表达式时,DeltaLake表返回行数过少的问题。此类子表达式现在会作为显式的未知谓词报告给 delta-kernel,而不再被当作子迭代器的结束,此前后者会导致外层合取式被静默截断。#112652 (groeneai)。 - 修复了
ALTER TABLE ... EXECUTE remove_orphan_files会删除 Iceberg 表中仍在使用的metadata/version-hint.text的问题。该文件的可达集合条目是通过字符串拼接构建的,拼接时假定某个值以斜杠结尾,但该值实际上从不带斜杠,因此真正的 hint 文件始终不会被识别为可达文件,一旦早于older_than阈值就会被删除。若设置了iceberg_use_version_hint = 1,该表随后将完全无法读取。#113548 (groeneai)。 - 修复了对经
ALTER TABLE ... MODIFY COLUMN变为Nullable的 Iceberg 列进行筛选时出现LOGICAL_ERROR的问题。#114521 (groeneai)。 - 修复了带有
ENGINE = URL(...)定义的ATTACH TABLE未检查 URL 协议所分派到的引擎的TABLE ENGINE授权的问题。此前,仅持有TABLE ENGINE ON URL权限的用户可以附加并读取基于File、S3、AzureBlobStorage或HDFS的表,而CREATE TABLE会正确拒绝此类操作。#115914 (groeneai)。 - 修复了在同时公布 IPv4 和 IPv6 地址、但仅有一种地址族可路由的主机上,出站 HTTP 请求 (例如 `aiGenerate`、`url` 表函数、S3) 因 `No route to host` 而失败的问题。现在,当第一个解析地址因网络错误失败时,HTTP 连接池会回退到下一个解析地址,而不是在首次请求时就直接抛出错误。#103786 (alexey-milovidov)。
- 支持将由双字段
{key, value}记录组成的 Avroarray读取到 ClickHouse 的Map列中。Iceberg 和 Spark 对键为非字符串类型的MAP<K, V>正是采用这种编码 (Avro 原生 map 仅支持字符串键) 。此前此类文件只能按Array(Tuple(key, value))读取,按Map(K, V)读取则会报错Type Map(...) is not compatible with Avro array。#109289 (groeneai)。 - 修复了当元数据文件的版本号全为数字但超出 32 位整数范围 (例如
v99999999999999999999.metadata.json) 时读取 Iceberg 表出错的问题。此前此类文件名会引发含义不明的std::out_of_range(STD_EXCEPTION) ,而不是清晰的BAD_ARGUMENTS错误。#109619 (groeneai)。 - 修复了经 gzip 压缩的 Iceberg 元数据文件的文件名问题。ClickHouse 此前将其写为
v{N}.gzip.metadata.json(沿用了 HTTPContent-Encoding标记) ,而 Iceberg 规范要求使用gz扩展名,即v{N}.gz.metadata.json。这导致 Spark 及其他 Hadoop-catalog 读取器无法找到 ClickHouse 写入的元数据。现在 ClickHouse 会写入v{N}.gz.metadata.json,同时为保持向后兼容,仍支持读取旧的gzip文件名。#109812 (groeneai)。 - 修复了写入格式为
Avro的 Iceberg 表会将声明为"required": false且类型为list、map或struct的字段序列化为必需字段 (不带["null", T]union) 的问题。该问题导致数据文件自身的 schema 与表元数据不一致,其他 Iceberg 读取器会将其视为必需字段。现在此类字段会按照 Iceberg 规范中可选字段所用的["null", T]union 形式写入。#112648 (groeneai)。 - 修复了当 Iceberg
snapshot-log中同一snapshot-id出现多次时 (回滚后会出现这种情况) ,system.iceberg_history中的made_current_at报告的是快照最早成为当前快照的时间、而非最近一次时间的问题。#113598 (groeneai)。 - 修复了当命名集合设置
http_client = 'gcp_oauth',且 Google OAuth2 令牌端点接受连接但始终不响应时,BACKUP/RESTORE ... TO S3、GCS 磁盘以及s3表函数可能挂起长达一小时的问题。Bearer 令牌请求不再沿用调用方的数据传输请求超时设置,其响应等待时间上限为 10 秒,与 STSAssumeRole请求的上限保持一致。#115531 (groeneai)。 - 修复了文件系统缓存中的一个逻辑错误 (
Expected file ... not to exist) :当后台缓存下载因非ErrnoException的异常而失败时 (例如对 Iceberg 表执行OPTIMIZE期间) ,会遗留一个空的孤立缓存文件,进而触发该错误。#110549 (groeneai)。 - 修复了按最大条目数配置的缓存 (
SLRU策略) 在达到该数量的条目均被访问至少两次后,会静默停止接纳新条目的问题。受影响的缓存包括 Iceberg 和 Paimon 元数据文件缓存、Parquet 元数据缓存、文本索引缓存、向量相似度索引缓存、已编译表达式缓存以及 ObjectStorageQueue 文件状态缓存。#115517 (groeneai)。 - 修复了可变的
snapshot/LATEST提示被并发替换时,读取 Paimon 表可能失败的问题。现在,无效或过期的提示会安全地回退为列出快照。#112010 (JiaQiTang98)。 - 当输入缓冲区 (例如设置了
restricted_seek = true的 S3 读取缓冲区) 拒绝 minizip 请求的寻道或读取操作、导致 zip 归档无法解包时,现在会显示真实的底层异常。此前,实际错误会被笼统的Couldn't unpack zip archive: Code = -100/Couldn't open zip archive消息所掩盖。#105103 (groeneai)。 - 修复了元数据不含 refs 时的 Iceberg 写入问题 #106896 (AVMusorin)。
- 修复了向 Iceberg 表插入数据时抛出异常的问题:该表的元数据由 external engine 创建,且省略了可选的
snapshots、metadata-log或snapshot-log数组。现在此类插入可以成功执行,不再失败。#107473 (tiandiwonder)。 - 修复了向 S3 上传数据 (例如备份) 时,若因瞬时读取错误而重试,可能出现
ReadBuffer is canceled. Can't read from it.错误的问题。#108573 (groeneai)。 - 修复了调度最终的异步 S3/Azure 分段上传完成任务失败时 (例如线程池耗尽) ,可能出现
std::future_error(“The associated promise has been destructed prior to the associated state becoming ready”) ,并在 debug/sanitizer 构建中导致服务器中止的问题。现在会报告真实的调度错误。#108730 (groeneai)。 - 修复了将约 2262 年之后的 ORC 时间戳读取到标度小于 9 的
DateTime64列时出错的问题。原生 ORC 读取器以前会先将所有时间戳统一转换为固定的DateTime64(9)中间类型,而在纳秒标度下这会导致Int64溢出,并以VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE拒绝此类值,即便所请求的DateTime64标度 (例如 Iceberg 生成的DateTime64(6)) 完全能够表示该值。现在时间戳会直接按所请求的标度读取;若目标标度仍无法容纳该值,则遵循date_time_overflow_behavior设置。#109302 (groeneai)。 - 读取 schema 中包含不受支持的嵌套类型 (例如
ROW字段) 的 Paimon 表时,现在会报告明确的BAD_ARGUMENTS错误并指明具体的不受支持类型,而不再返回错误码为 0 且不带任何消息的DB::Exception. (OK)。#109762 (groeneai)。 - 修复了无法读取基于同一源列多次分区的 Iceberg 表 (例如
PARTITIONED BY (hours(ts), ts)) 的问题。此前读取此类表会报错Cannot add column ...: column with this name already exists (ILLEGAL_COLUMN)。#109895 (groeneai)。 - ClickHouse 写入 Iceberg 表的 Avro 和 ORC 格式数据文件现在会嵌入 Iceberg 字段 ID (Avro 使用
field-id,ORC 使用iceberg.id/iceberg.required类型属性) ,且 ORC 的String列会以 ORCstring而非 binary 类型写入。此前只有 Parquet 会嵌入字段 ID,因此符合规范的读取器 (例如 Spark/iceberg-java) 在列重命名后读取 ClickHouse 写入的 Avro 行时会静默返回 NULL,而 ClickHouse 写入的 ORC 文件则根本无法读取。#109994 (groeneai)。 - 修复了当 Iceberg 表中存在比所有位置删除文件都新的非 Parquet 格式 (例如
ORC) 数据文件时,对其执行OPTIMIZE TABLE会出现逻辑错误ChunkInfoRowNumbers does not exist的问题。#110107 (alexey-milovidov)。 - 修复了通过
s3和file从未压缩的STOREDzip 条目中读取大型Parquet文件时出错的问题。#110495 (Gudauu)。 - 后台调度池 (例如全局线程池耗尽时的
iceberg池) 启动失败不再导致服务器中止,该错误现在会作为可恢复的异常抛出。此外,读取system.background_schedule_pool时也不会再顺带创建这些池。#111209 (groeneai)。 - 修复了 Paimon REST 目录中的 DLF 身份验证问题:请求签名仅计算一次并被反复复用,导致首个请求之后的所有目录请求均因 HTTP 401 失败,SHOW TABLES 也只返回空列表。同时修复了表存在性检查中的 HTTP 404 检测问题。#112015 (JiaQiTang98)。
- 修复了对因位置删除而被清空的
Iceberg数据块进行分区时出现LOGICAL_ERROR(partitions_count > 0) 的问题,例如在压缩包含已被完全删除数据文件的分区Iceberg表时。#112432 (PedroTadim)。 - 修复了 Azure 批量删除对象时,若批次请求本身失败,
system.blob_storage_log中不会记录任何 Delete 事件,导致整个批次都没有日志的问题。现在发生批次级失败时,会为每个对象各记录一条 Delete 事件。#112873 (arsenmuk)。 - 修复了读取按 precision 高于毫秒的
TIMESTAMP列分区的Paimon表时失败并报错scale 6 is not supported, only support scale <= 3的问题。#113401 (JiaQiTang98)。 - 修复了读取数据湖表时,若其 schema 中声明了名称为空的列则会导致崩溃的问题。格式错误的 Iceberg 元数据会被拒绝并报错
ICEBERG_SPECIFICATION_VIOLATION;由 catalog、Delta Lake 或 Paimon 提供的 schema 会被拒绝并报错AMBIGUOUS_COLUMN_NAME。该检查无条件执行,因此即使某个 Iceberg 表只是保留了一个未使用且包含空字段名的历史 schema,该表也会变为不可读,而不是在读取到该 schema 时中止。#114394 (groeneai)。 - 读取 Iceberg 表时,若其元数据描述了 Iceberg 规范所禁止的 schema 演进,不再导致服务器中止。
IcebergSchemaProcessor中的四种违反规范的情况此前会被报告为LOGICAL_ERROR(被视为断言失败) ,或在未经检查的情况下触发致命断言;现在会抛出ICEBERG_SPECIFICATION_VIOLATION。#114518 (groeneai)。 - 修复了在基于 musl 的构建中,
url/urlCluster表函数的_time虚拟列始终为NULL的问题,其原因是对 HTTPLast-Modified头的解析方式不可移植。#111619 (thevar1able)。 - 修复了在启用
allow_experimental_url_wildcard_from_index_pages的情况下使用CREATE TABLE ... AS url('http://host/**/', ...)创建表后,服务器无法启动的问题。加载此类表的元数据时会重新执行实验性功能检查,并因SUPPORT_IS_DISABLED失败,导致启动中止。#115095 (groeneai)。 URL数据库引擎的表不再向没有读取源授权的用户泄露本地文件是否存在:仅需SHOW TABLES特权的EXISTS TABLE以及表的解析过程,都不再在授权确认之前探测文件系统。#113029 (alexey-milovidov)。- 将
query_masking_rules应用于通过Exception::addMessage追加的消息,确保在配置了脱敏规则时,jdbc()/odbc()错误信息中(in file/uri ...)后缀里经过 URL 编码的凭证不会泄露。#106916 (gaurav0107)。
格式与摄取相关修复
- 对 Arrow
time32/time64进行无 schema 读取 (例如SELECT * FROM file(..., 'Arrow')) 时,现在会推断为Time64,而不再是此前的DateTime64。任何依赖旧推断类型的下游逻辑在升级后都将失效。此外,还新增了将Time/Time64导出到 Arrow 的支持,并会根据精度选择相应的 Apache Arrow 时间类型。#104316 (Maoyao233)。 - 修复了在启用延迟列复制 (
enable_lazy_columns_replication) 时,若INSERT因批处理中途出错而回滚 (例如在Buffer表、异步插入或Kafka/RabbitMQ/FileLog引擎中) ,可能导致结果错误或越界读取的问题。#108935 (groeneai)。 - 修复了一个解析器不一致问题:
INSERT列列表可以接受以t.* LIKE '<pattern>'/t.* ILIKE '<pattern>'形式编写的限定列匹配器,却拒绝其规范形式t.COLUMNS('<regexp>'),导致查询格式化无法往返一致 (在 debug/sanitizer 构建中还会导致服务器中止) 。#109176 (groeneai)。 - 修复了向 Microsoft Fabric / OneLake
DataLakeCatalog表执行INSERT时报IncorrectEndpointError(HTTP 400) 错误的问题:现在 ADLS Gen2 (DFS) 写入会路由到.dfs端点主机,而不是.blob主机。注意:使用remote_url_allow_hosts时,必须将.blob(读取) 和.dfs(写入) 两个 Fabric 主机都加入允许列表,才能执行INSERT。#110290 (zlareb1)。 - 修复了通过数据湖表函数写入 (例如
INSERT INTO FUNCTION icebergS3(...)) 时,生成的 Parquet 文件中字符串列丢失String类型注解,导致 Spark 等外部读取器无法读取写入数据的问题。此类写入现在与通过表引擎写入时使用相同的格式设置。#110465 (tiandiwonder)。 - 修复了通过 Arrow Flight 登录后
system.session_log无法读取的问题:interface列为Enum8类型,但其枚举定义中缺少ArrowFlight值,因此通过 Arrow Flight 协议登录时会写入原始值10,任何读取此类行的SELECT都会抛出异常Unexpected value 10 in enum。#110758 (alexey-milovidov)。 - 修复了
TSV系列格式的 schema 推断问题:带前导零的小数值 (如0.0或0.5) 会被推断为String,而CSV能正确推断为Float64。此外,若首行均为此类值,还会被TSV的表头自动检测误判为表头,从而在结果中丢失。同时修复了TSKV对使用转义序列书写的值 (如x=1\x2E5) 推断出数值类型、随后却解析失败的问题。对于前导零属于整数填充的值 (如007) ,仍会推断为String,因为TSV值解析器无法将其读回。#112226 (groeneai)。 - 修复了 schema 推断会为值解析器无法读回的文本值推断出数值类型的问题。此前推断会接受悬空的指数 (
1e+) 、缺失的尾数 (.) 或重复的符号 (++inf) ,而readFloatTextPrecise在按推断出的 schema 读取时会以CANNOT_PARSE_NUMBER拒绝这些值;对于Dynamic列,则会在 INSERT 时报错。现在推断会使用读取器实际所用的解析器来校验数值。此修复还消除了推断类型受max_read_buffer_size影响的情况,并使0e5等有效的前导零指数形式在 TSV 中也能像在 CSV 中一样被推断为Float64。同时还修复了格式错误的指数形式。#112453 (groeneai)。 - 修复了基于行的输入格式在解析单个块时,
KILL QUERY和max_execution_time可能长达数分钟不生效的问题。现在基于行的输入格式每 8192 行检查一次查询是否已取消,因此被终止的插入操作 (尤其是后台异步插入刷新,每个块最多解析max_insert_block_size行) 会及时停止,而不会一直运行到块末尾。#112646 (groeneai)。 - 修复了对于 schema 已缓存的数据源,推断出的列类型取决于先前查询顺序的问题。会影响推断类型的设置未纳入 schema 推断缓存键,导致首个查询的设置值决定了后续所有查询看到的类型:
input_format_try_infer_exponent_floats、max_parser_depth、input_format_json_infer_array_of_dynamic_from_array_of_different_types,以及针对Parquet的input_format_parquet_local_time_as_utc、input_format_parquet_allow_geoparquet_parser、input_format_parquet_skip_columns_with_unsupported_types_in_schema_inference和schema_inference_make_json_columns_nullable。此外还为Form注册了缺失的缓存键获取器,并使Template的获取器使用其自身行格式的转义规则。#113533 (groeneai)。 - 修复了当外层查询末尾带有
SETTINGS子句时,view和viewIfPermitted表函数的子查询参数格式化错误的问题。此类查询会被格式化为view((SELECT ...)),而该形式无法被重新解析,导致查询无法通过内部的“格式化-解析-格式化”检查,并抛出Inconsistent AST formatting。#114658 (groeneai)。 - 修复了格式自动检测时 JSON 数据被误识别为 TSKV 的问题。#106009 (Avogar)。
- 现在将超出一天内有效时间范围 (负值或
>= 24h) 的Time/Time64值导出为Arrow格式时,会直接报出明确的错误,而不再写入无效的 Arrowtime32/time64数据。#107179 (tiandiwonder)。 - 修复了读取
Arrow、ArrowStream以及基于 Arrow 的ORC文件时,若时间戳列的时区为固定数值 UTC 偏移 (例如+05:30、-08:00、00:00) 或非 IANA 标记fixed,会报Cannot load time zone ...(BAD_ARGUMENTS) 错误而失败的问题。#108633 (groeneai)。 - 现在
Nullable(Tuple(...))列会序列化为单个 CSV 字段,而不再展开为多个独立的列。此前非空值会被写成多个 CSV 字段,而NULL只是单个\N,导致列数因行而异,破坏了CSVWithNames/CSVWithNamesAndTypes的表头以及数据的往返读写。#108959 (groeneai)。 - 修复了对
MsgPack格式进行 schema 推断时内存分配过多的问题:对于已损坏或经模糊测试生成的输入,即使其 array/map/string/binary 头部声明了极大的元素数量,也不会再触发单次数 GB 的内存分配 (此类输入现在会作为格式错误的输入被拒绝) 。此修复解决了在 sanitizer 下出现的allocation-size-too-big中止问题,以及发布构建中的内存不足问题。#109019 (groeneai)。 - 修复了在设置
output_format_arrow_low_cardinality_as_dictionary = 1时,将LowCardinality(Time)列写入Arrow格式会触发LOGICAL_ERROR的问题。#109730 (groeneai)。 - 修复了读取已损坏的
Native格式数据流时的问题:当其中的Dynamic类型数量或JSON/Object路径数量接近SIZE_MAX时,此类格式错误的输入现在会被拒绝并报出明确的INCORRECT_DATA错误,而不再抛出未捕获的std::length_error。#110590 (alexey-milovidov)。 - 修复了合并以旧版 (版本 0) 状态格式序列化、且包含
Bool值的sumMap/sumMapWithOverflow/sumMapFiltered聚合状态时出现LOGICAL_ERROR: Cannot sum Bools(在 debug/sanitizer 构建中会导致服务器中止) 的问题。此修复还纠正了版本 0Bool状态下两种静默返回错误结果的情况:Bool类型的 map 键未在各状态之间去重,以及零值压缩时删除了错误的条目。#110922 (groeneai)。 - 修复了当输入数据解析结果为零行时 (例如空 JSON,或不含任何要素的 GeoJSON
FeatureCollection) ,format表函数抛出NOT_FOUND_COLUMN_IN_BLOCK的问题。现在会返回列结构正确的空结果。#111428 (groeneai)。 - 现在可以读取这样的 GeoParquet、Arrow 和 ArrowStream 文件:其 WKT 编码的几何列使用了非大写的类型关键字 (
point(1 2)) 或空容器 (LINESTRING EMPTY、POLYGON()、POLYGON(())) 。此前,尽管相同的字符串可以用readWKT函数正常解析,此类文件在导入时仍会因BAD_ARGUMENTS或CANNOT_PARSE_NUMBER而失败。此修复还解决了无法回读存储空几何对象wkt输出 (即LINESTRING()) 的文件的问题。#112020 (groeneai)。 - 修复了
auto和none压缩提示在非全小写书写时抛出Unknown compression method的问题,例如file('data.csv.gz', 'CSV', 'x String', 'AUTO')。GZIP等编解码器名称此前就已支持不区分大小写;现在这两个特殊提示也与之保持一致。#113631 (groeneai)。 - 修复了在
CustomSeparated、Regexp和Template格式中使用CSV转义规则时,读取第一个元素为NULL的Tuple列出错的问题。在这些格式中,裸Tuple的每个元素各占一个字段,因此开头的\N字段对应的是该元素,而非整列。此前它会被当作整列读取,导致其余元素字段错位到后续列中,使CustomSeparated无法回读自身的输出。#114471 (groeneai)。 - 修复了
Regexp输入格式会静默丢弃匹配字段中未解析的剩余部分的问题,该问题会导致存储被截断或凭空生成的值,而不是报告错误:在JSON规则下,将v=-1读入UInt64会得到0,将v=2020-01-01junk读入Date会得到1975-07-14。现在,在Escaped、CSV和JSON规则下,格式错误的字段会被拒绝,与文档中这些规则所对应格式的行为保持一致。在Raw规则下,包含制表符的匹配字段现在会被完整读取,而不会在制表符处被截断。#114520 (groeneai)。 - 修复了
CREATE INDEX/CREATE HYPOTHETICAL INDEX表达式无法通过“格式化-解析-格式化”往返校验时触发的Inconsistent AST formatting逻辑错误 (在 debug 和 sanitizer 构建版本中会导致服务器中止) ,例如CREATE HYPOTHETICAL INDEX i0 ON t0 ((a())) TYPE a和CREATE INDEX i0 ON t0 ((a, b).1) TYPE minmax。#109175 (groeneai)。 - 修复了 Parquet v3 读取器中的一个逻辑错误 (
Logical error: 'KeyCondition uses PREWHERE output') ,该错误会在格式级键条件引用了未从 Parquet 文件中读取的列时出现。#109267 (groeneai)。 - 修复了预定义 HTTP handler 在缺少请求头时抛出异常的问题 #108324 (vitlibar)。
- 修复了基于行的输入格式 (例如
TSV/CSV) 解析输入失败、且底层读取已被取消时 (例如 HTTP 分块格式错误或请求体被截断) 可能出现的Logical error: 'ReadBuffer is canceled. Can't read from it.'问题。现在生成详细的解析诊断信息时,不再从已取消的缓冲区中读取。#109708 (groeneai)。 - 当流式解析成功回退到 SQL 表达式解析时,
Values格式不再在system.errors和system.error_log中记录解析错误。#111141 (pamarcos)。 - 修复了在已停止的
RabbitMQ表上执行SYSTEM REFRESH时,有时无法消费积压消息的问题。一次 REFRESH 只允许执行一个额外的 (不按常规调度的) 流式处理周期,但由于 AMQP 投递循环才刚以异步方式启动,该周期可能立即返回零行,白白耗掉这唯一一次机会,导致消息直到下一次SYSTEM START前都无法被消费。#111480 (groeneai)。 - 修复了设置了
nats_stream的NATS表在 NATS 服务器重启后静默停止消费消息的问题。现在JetStream订阅会自动重新建立,无需再执行DETACH TABLE和ATTACH TABLE。#112828 (groeneai)。 - 对于过大的
kafka_num_consumers值,现在会直接拒绝并给出明确的错误信息,而不是在Kafka表引擎内部出现内存分配失败。此前,在启用kafka_disable_num_consumers_limit时,此类值会引发std::length_error异常。#114764 (alexey-milovidov)。 - Arrow Flight server:现在接受不带填充的 Base64 编码
Basic身份验证凭证 (基于 Go 的 Flight 客户端,例如 ADBC Flight SQL 驱动程序,会发送此类凭证) ;当authorization请求头格式错误时,会返回正确的身份验证错误,而不是笼统的Unexpected error in RPC handling。#115085 (alexey-milovidov)。 - Arrow Flight 服务器:拒绝缺少用户名/密码分隔符的格式错误的 Basic 身份验证凭证。#115347 (alexey-milovidov)。
数据类型、函数与序列化相关修复
- 修复了逻辑错误
Stream <col>.variant_discr ... is not found(在 debug 和 sanitizer 构建中会导致服务器中止) :在包含 Wide parts 的表上,当ALTER TABLE ... MODIFY COLUMN将某列更改为带有动态子列的类型 (例如将Variant改为Dynamic) ,且随后读取或合并该 part 时,会出现此问题。#110204 (groeneai)。 - 修复了读取
Nullable(Tuple(...))列的子列时的问题:当该列的元素为非 Nullable 的LowCardinality(T),且同一查询还读取了其父级子列时会触发该问题。在 Compact part 上,父级子列会返回错误的值,或查询失败并报错Unexpected return type from assumeNotNull,或服务器因string_view加固断言而被终止。原因在于提取出的子列被反序列化到LowCardinality(Nullable(T))缓冲区中,而该缓冲区的子流随后又被父级子列的读取所共享。#112232 (groeneai)。 - 修复了
LOGICAL_ERROR“Not-ready Set is passed as the second argument for functionglobalNullIn” 以及查询真实错误信息丢失的问题:当基于统计信息的 part 裁剪在索引分析期间推测性地执行IN/GLOBAL IN子查询,而该子查询执行失败时,可能会出现此问题。#114121 (groeneai)。 - 修复了读取使用
Quantized('product', ...)编解码器的列的product_quantization_codebook子列时出现Cannot read all data of type FixedString的问题。每个 part 的码本写在所有粒度的数据之后,因此不以标记划分边界;若读取的标记范围在该 part 的最后一个标记之前结束,码本可能读取不完整。#112818 (alexey-milovidov)。 - 对于
Dynamic列中的Map值,不再写入Map布局与自身元数据不一致的 part。此前,仅map_serialization_version不同的表会共享同一个缓存的序列化对象,导致某个 part 可能采用basicMap 布局,而其元数据却声明为with_buckets,之后读取时便会失败并报错LOGICAL_ERROR: Stream ...buckets_info ... is not found。早期版本已按此方式写入的 part 仍无法读取,只能将其删除。#113514 (groeneai)。 - 修复了
ALP、FPC和GCD计算编解码器哈希时遗漏由类型推导出的参数的问题。在 Compact part 中,写入器会让编解码器哈希相同的列共享同一个压缩流,因此使用同一编解码器但值宽度不同的两列会发生冲突,共用一个宽度错误的编解码器对象。宽度不一致时,合法的插入会因CANNOT_COMPRESS被拒绝;即使未报错,其中一列的压缩效果也会比预期更差。#114189 (groeneai)。 - 修复了错误的索引裁剪问题:当表的 sorting key 用
toDateTime包装Date列 (例如ORDER BY toDateTime(date_column)) ,且查询以类似WHERE date_column >= '...'的比较条件对原始列进行过滤时会出现该问题。对于超出DateTime范围 (2106-02-07之后) 的Date值,toDateTime(Date)会溢出,因此存储的键并非单调;由于对这种键/谓词组合使用主键裁剪可能会丢弃包含匹配行的粒度,ClickHouse 将不再对其使用主键裁剪。#101814 (nihalzp)。 - 修复了将带有
DEFAULT的Nullable列转换为其他类型 (例如Nullable(UInt8)→String、LowCardinality(String)或Array(UInt8)) 时ALTER MODIFY COLUMN执行失败的问题。#102156 (il9ue)。 - 修复了
StorageSQLite和sqlite()表函数在将WHERE谓词下推到 SQLite 时 SQL 字面量转义不正确的问题:单引号和控制字符 (\n、\r、\t、\) 会被转义为反斜杠形式,而 SQLite 并不识别这种转义,从而导致语法错误或错误的查询结果。同时修复了下推到 PostgreSQL 的字符串字面量的转义问题:嵌套在IN列表中的字符串仍沿用 ClickHouse 的转义方式,且控制字符以反斜杠序列形式发送,而 PostgreSQL 会将其解析为不同的字节。#104217 (tiandiwonder) 。 - 修复了在启用
query_plan_convert_join_to_in且 SELECT 引用源数组列时,INNER JOIN ... ON arrayJoin(...) = ...查询抛出NOT_FOUND_COLUMN_IN_BLOCK异常的问题。#104809 (tiandiwonder) 。 - 修复了右侧操作数为非常量且引用当前行中列的 IN 和 NOT IN 表达式的问题,并使新 analyzer 对右侧 tuple 的处理与 ClickHouse 现有的 IN 语义保持一致。在旧 analyzer 下,作为右侧操作数的单独源列 (
x IN (arr)) 仍会被解析为表名,且不在作用域内。#104993 (niyue) 。 - 修复了在
DirectKeyValueJoin使用String或Nullable(String)键时,对EmbeddedRocksDB、Redis和KeeperMap表执行JOIN可能静默返回零行的问题。#105253 (vdimir) 。 - 修复了当非等值
JOIN ... ON谓词引用Nothing类型的列 (例如由ARRAY JOIN []生成的列) 时出现的LOGICAL_ERROR(“Unexpected expression in JOIN ON section. Expected boolean (UInt8), got ‘Nothing’”) 。#106981 (groeneai) 。 - 修复了一个
Inconsistent AST formatting逻辑错误:当带别名的 lambda 位于表达式列表的非首位,并被用作访问运算符 (.Ntuple 元素或[]数组元素) 的操作数时,可能导致 debug 和 sanitizer 构建中的服务器异常终止,例如SELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t。#107092 (groeneai) 。 - 嵌套在另一个分布式查询中的 cluster 表函数 (
urlCluster、fileCluster、s3Cluster等) ,例如clusterAllReplicas(..., urlCluster(...)),现在会直接以BAD_ARGUMENTS错误被拒绝,而不再因逻辑错误 (Distributed task iterator is not initialized) 而失败。#107107 (groeneai) 。 - 修复了
values表函数在使用无法被窄浮点列精确表示的十进制字面量 (例如用于Float32列的0.1) 时报ARGUMENT_OUT_OF_BOUND错误的问题,例如SELECT * FROM values('x Float32', 0.1)。现在此类值会被接受并转换为最接近的可表示值,与CAST和INSERT ... VALUES的行为一致。#108055 (alexey-milovidov) 。 - 修复了
mapFilter、mapSort(及其变体) 和mapConcat会丢失Map键和值类型中LowCardinality的问题。此前,对Map(LowCardinality(String), String)列执行mapFilter会返回Map(String, String),这可能损坏通过CREATE TABLE ... AS SELECT创建的表的元数据,并导致CHECK TABLE失败。#108057 (alexey-milovidov) 。 - 修复了被取消或被
KILL的INSERT在构建跳数索引 (例如在高基数列上的无上限set(0)索引) 时仍会长时间运行的问题。现在查询被取消后,索引构建会立即停止。#108351 (tiandiwonder)。 - 修复了对
primes表函数执行SELECT时无法响应取消操作的问题:当step(或limit) 较大时,查询在KILL QUERY或超时后仍可能长时间运行。现在查询会立即停止。#108353 (tiandiwonder)。 - 修复了名称中包含子串
INT的数据类型名称 (例如在数据类型位置使用的类函数名称quantileInterpolatedWeighted) 的解析问题。此类名称会被误识别为 MySQL 整数类型,其第一组(...)参数会被悄无声息地当作显示宽度修饰符吞掉,从而可能导致查询格式化无法正确往返还原。#108354 (groeneai)。 - 修复了一处不一致问题:格式错误的
ARRAY JOIN后接逗号和带括号的表列表时,会被误解析为交叉连接,而不是直接报错拒绝。#108365 (Algunenano)。 - 修复了分布式查询在对结构相同的重复
ALIAS列进行去重的同时,又引用了带有key = value命名集合参数的表函数 (例如oss(s3_conn, filename = '...')) 时抛出的LOGICAL_ERROR(“Invalid action query tree node …”) 异常。#108435 (groeneai)。 - 修复了在分布式表上调用带有多个
LowCardinality参数的函数时可能出现的逻辑错误 (在发布构建中表现为异常,在调试和 sanitizer 构建中会导致服务器中止) ,例如将concatAssumeInjective((SELECT toLowCardinality('p')), s)与remote()配合用作GROUP BY键。相应的错误消息为Default functions implementation for LowCardinality is supported only with a single LowCardinality argument或Expected the argument ... to have N rows, but it has M。#108871 (groeneai)。 - 修复了在服务器端解释的
DateTime/DateTime64字符串字面量 (异步INSERT、SELECT字面量) 会忽略use_client_time_zone的问题。现在启用use_client_time_zone时,客户端会将本地时区作为session_timezone传递给服务器,使服务器端解析结果与同步INSERT路径保持一致。#109051 (groeneai)。 - 修复了
max_execution_time(配合timeout_overflow_mode = 'throw') 有时始终无法取消查询的问题:当内部超时监视器正在等待一个截止时间较晚的查询时,随后注册的截止时间较早的查询可能被完全遗漏,导致其运行时间远远超出时间限制。#109792 (tiandiwonder)。 - 修复了在启用分析器时,对
Distributed表的查询同时使用ORDER BY和变为Nullable的_shard_num(或shardNum()) (例如在join_use_nulls = 1的FULL JOIN中) 时出现的NOT_FOUND_COLUMN_IN_BLOCK错误。#109798 (groeneai)。 - 修复了启用
enable_join_runtime_filters = 1(自 26.2 起默认开启) 时,若构建端连接键为包含 NULL 的LowCardinality(Nullable(...)),且运行时过滤器回退为布隆过滤器,连接可能抛出NOT_IMPLEMENTED错误 (“Method getDataAt is not supported for Nullable(String)”) 的问题。#109824 (groeneai)。 - 修复了在高阶函数需要具体值的位置传入 lambda 表达式时导致服务器崩溃的问题 (例如作为
arrayFold的累加器,如arrayFold(lambda, arr, another_lambda)) 。当enable_analyzer = 0时,此类查询现在会被拒绝并返回ILLEGAL_TYPE_OF_ARGUMENT,而不再导致崩溃。#109840 (groeneai)。 - 禁止在行策略过滤器中使用
arrayJoin的别名unnest,从而修补了此类策略可能在读取时引发column->size() == num_rows逻辑错误的漏洞。#109973 (Algunenano)。 - 修复了当同一查询中同时读取完整元组 (例如
SELECT *) 时,若通过tupleElement(t, 'name')、tupleElement(t, N)或t.N访问字段,定义在Tuple子列上的跳过索引不会生效的问题。现在这些访问形式都会与按名称访问子列t.name一样裁剪颗粒。#110056 (groeneai)。 - 修复了当
Array(String)列带有text、tokenbf_v1或ngrambf_v1跳过索引时,将该列与数组字面量进行比较 (arr = ['x']) 会出现BAD_GET错误的问题。现在索引会将此类比较视为全量扫描,而不会导致整个查询失败。#110057 (groeneai)。 - 修复了在应用阶段列已存在时,
ALTER TABLE ... ADD COLUMN IF NOT EXISTS误报ILLEGAL_COLUMN错误的问题。该问题出现在同一语句中使用IF NOT EXISTS重复添加同一列,或在准备阶段与应用阶段之间有并发的ALTER添加了该列的情况下。#110080 (groeneai)。 - 修复了当
identity()(或标量子查询结果) 包装了含嵌套LowCardinality的值,且查询使用WITH TOTALS/WITH ROLLUP时出现的LOGICAL_ERROR(Bad cast from type ColumnLowCardinality to ColumnString) 。#110138 (groeneai)。 - 修复了对元组表达式使用
GROUP BY ALL并同时使用ORDER BY时出现的NOT_FOUND_COLUMN_IN_BLOCK错误。#110206 (alexey-milovidov)。 - 修复了当表的
CHECK约束引用了子列 (例如Nullable列的x.null或Array的arr.size0) 时,向该表执行INSERT出现NOT_FOUND_COLUMN_IN_BLOCK错误的问题。#110208 (alexey-milovidov)。 - 修复了 optimize_and_compare_chain 优化 (默认启用) 导致查询结果错误的问题:当比较链中混用了具有特定成对转换规则的类型 (例如 Enum 与 String、Decimal 与 Float64、不同宽度的 FixedString) 时,由 a < b AND b < c 通过传递性推导出的条件可能采用与原始条件不同的比较语义。现在仅在共享同一比较顺序的类型组内推导传递条件。#110621 (yariks5s)。
- 修复了
optimize_injective_functions_in_group_by会改变GROUP BY GROUPING SETS和GROUP BY ... WITH TOTALS查询结果的问题。文档中说明该设置不会改变查询结果,但消除分组键上的单射函数后,对于聚合集合中不包含该键的行 (即该键不属于某个GROUPING SETS集合) 或WITH TOTALS行,会产生错误的值 (或丢失一行) 。该错误值可能恰好与某个真实的键值相同,导致同一结果集中的超聚合行与真实分组无法区分。#110721 (groeneai). - 修复了将
median/quantile(基于 ReservoirSampler) 聚合函数状态与极大的整数常量相乘 (例如medianState(x) * 18446744073709551615) 时服务器挂起的问题。此前该查询无法被取消,并可能无限期运行下去。#110779 (groeneai). - 修复了对
JSON参数调用getSubcolumn并传入内部类型提示子列名 (即以反引号类型标记开头的名称) 时发生崩溃 (查询分析期间空指针解引用) 的问题。#110940 (groeneai). - 修复了
map[key]返回靠后的重复键的值、而非第一个键的值的问题。当Map列包含重复键时,map[key]的结果可能取决于同一块中位于其前面的行以及optimize_functions_to_subcolumns设置,导致针对同一行的SELECT与WHERE结果不一致。#111246 (groeneai). - 修复了在
use_variant_default_implementation_for_comparisons = 0时,若AND链将某列与非Nullable类型的 NULL 值常量 (例如值为 NULL 的Variant) 进行比较,逻辑表达式优化器会抛出逻辑错误!rhs_literal->getValue().isNull()的问题。#111292 (groeneai). - 修复了当查询使用
set跳数索引,且谓词形如(x AND <null-value>) OR y、其中 NULL 由函数产生 (例如toInt64OrNull('x')、nullIf(1, 1)、CAST(NULL AS Nullable(Int64))) 时返回错误结果的问题。此类值会被__bitWrapperFunc包装并传播NULL,而不是“未知”掩码,导致 set 索引可能裁剪掉实际匹配的颗粒,使查询返回的行数少于预期。#111604 (groeneai). - 修复了启用 analyzer 时,
CREATE TABLE/ALTER TABLE会接受引用虚拟列 (如_table或_database) 的列DEFAULT/MATERIALIZED表达式的问题。向此类表插入数据会失败并报NOT_FOUND_COLUMN_IN_BLOCK错误,而MATERIALIZED列 (无法显式提供值) 更会导致该表永远无法插入数据。现在这些表达式会在定义时即被拒绝,与未启用 analyzer 时的行为保持一致。基于虚拟列的ALIAS列 (读取时计算) 和EPHEMERAL列 (不存储的插入输入) 仍可正常使用。#111776 (groeneai). - 修复了调用参数化视图时,若传入类型为
Array、Tuple或LowCardinality的子查询参数 (例如SELECT * FROM v(param = (SELECT groupArray(x) FROM t))) ,会报UNKNOWN_QUERY_PARAMETER错误的问题。#111790 (groeneai). - 修复了 analyzer 中将比较链改写为
IN/NOT IN的三个缺陷 (x = c1 OR x = c2 OR ...、x != c1 AND x != c2 AND ...以及has(const_array, x)) 。对于use_variant_default_implementation_for_comparisons = 0时的Variant表达式,该改写会将表达式的结果类型从UInt8变为Nullable(UInt8),导致在 debug 和 sanitizer 构建中由查询树校验检查抛出LOGICAL_ERROR。对于具有动态结构的表达式 (Dynamic、Array(Dynamic)、JSON) ,该改写会使原本正常的查询失败,并报错Illegal type ... of argument of function in,因为IN不接受此类参数。此外,当常量无法无损转换为表达式的类型时 (例如将带有具体时间的DateTime常量与Date列进行比较) ,两个方向的改写都会返回错误结果。#111924 (groeneai)。 - 修复了当查询使用并行副本、分布式表或外部聚合,或者状态存储在表中 (包括存储在
Dynamic值内部) 时,quantileDeterministic、quantilesDeterministic和medianDeterministic对相同数据每次运行都返回不同结果的问题。此版本之前以无版本号类型写法写入的状态仍保持原有行为,因为其布局无法更改。#112052 (alexey-milovidov)。 - 修复了向量搜索查询污染查询条件缓存而导致结果错误的问题。对带有
vector_similarity索引的表执行SELECT ... WHERE <condition> ORDER BY <distance function> LIMIT n查询时,可能会将某些 granule 错误地记录为不匹配<condition>,导致之后在同一张表上执行普通的SELECT ... WHERE <condition>时静默返回较少的行。现在,向量搜索的读取操作不再写入查询条件缓存。#112086 (groeneai)。 - 修复了
serialize_string_in_memory_with_zero_byte在序列化的查询计划中丢失的问题。当serialize_query_plan = 1时,禁用该设置的集群可能会在发起节点与执行反序列化计划的节点之间出现内存中字符串表示形式不一致的情况。原因是该设置在反序列化时会被读取,但在序列化时从未被写入,因此在执行节点上始终取其默认值。#112131 (groeneai)。 - 修复了
ON表达式包含常量合取项的JOIN返回错误结果的问题,例如ON l.id = r.id AND CAST(NULL AS Nullable(UInt8))。该常量会在查询计划优化过程中被静默丢弃,导致连接在执行时如同该常量不存在:对于永远不为真的条件,INNER、LEFT SEMI和RIGHT SEMI连接本应不返回任何行,却返回了匹配的行;而RIGHT ANTI本应返回所有行,却未返回任何行。#112155 (vdimir)。 - 修复了使用非
parameter = value赋值形式的参数调用参数化视图时返回错误结果的问题。在enable_analyzer = 0时,以及在默认设置下执行EXPLAIN SYNTAX时,诸如pv(concat(name, '!'))、pv(name, 'a')、pv(name != 'a')和pv(tuple(name = 'a'))之类的调用会将视图参数静默绑定到不相关的表达式上,而不是像 analyzer 那样报告UNKNOWN_QUERY_PARAMETER。现在,此类调用在两种执行路径上都会以相同方式被拒绝。#112194 (groeneai)。 - 修复了以下问题:当
CREATE VIEW或CREATE FUNCTION的定义以substring语法无法重新解析的形式调用substr、mid或byteSlice时,该语句会被接受,但 ClickHouse 为其写入的元数据并不是有效的 SQL。此后读取该定义会因SYNTAX_ERROR而失败;在服务器启动时,还会导致元数据加载中止,使服务器完全无法启动。现在此类定义可以正确地往返转换,形如substring(x, a, b, c)的现有元数据文件也恢复可读,因此受影响的服务器无需人工干预即可启动。#112195 (groeneai)。 - 修复了当主键为
Array或Tuple,且查询对其应用plus、minus、multiply、divide或intDiv时,出现错误结果、ORDER BY输出顺序错误以及BAD_TYPE_OF_FIELD异常的问题。复合值的算术运算是逐元素进行的,而复合值的比较则按字典序进行,因此主键分析不再将此类表达式视为单调。#112339 (groeneai)。 - 修复了包含
PASTE JOIN的查询被发送到其他服务器时 (例如左表为Distributed表或*Cluster表函数) ,远程服务器抛出Code: 62 ... You must not specify ANY or ALL for PASTE JOIN. (SYNTAX_ERROR)的问题。原因是格式化器会输出ALL PASTE JOIN,而解析器不接受这种写法,导致接收方服务器无法解析收到的查询。#112404 (groeneai)。 - 修复了
(SELECT 1) AS t(x)或WITH t(x) AS (SELECT 1)等列别名列表在view表函数内部不可见的问题:此前引用t.x会因UNKNOWN_IDENTIFIER而失败,而同样的写法在view之外却能正常工作。#112690 (groeneai)。 - 修复了
ARRAY JOIN子句不含任何表达式时查询格式化出现的逻辑错误。现在此类子句会在解析阶段以SYNTAX_ERROR被拒绝 (与空USING的处理方式一致) ,而不会再被接受并格式化为无法重新解析的文本。#112699 (groeneai)。 - 修复了为子查询准备的表达式动作在其构建上下文被释放后才执行时,
connectionId抛出Context has expired的问题。#112870 (clickgapai)。 - 修复了在连接过程中求值的非等值
JOIN ON条件包含arrayJoin时出现的逻辑错误和错误结果。现在hash、parallel_hash或grace_hash连接会以INVALID_JOIN_ON_EXPRESSION拒绝此类条件。如果展开操作仅依赖于某一侧,请在连接之前将其移至子查询中的ARRAY JOIN;如果arrayJoin的参数同时读取了两侧的列,则需要重写该条件。#112889 (groeneai)。 - 修复了
geohashesInBox在面积为零的区域 (例如geohashesInBox(0., 0., 180., 0., 12)) 上耗时无上限的问题。此类查询虽然能返回正确的单个 geohash,但每行会白白执行约 5e8 次空循环,且无视max_execution_time和KILL QUERY。#112976 (groeneai)。 - 当被标记为“无值写入”的
SETTINGS变更携带了true以外的值时,现在会拒绝该变更;并且在格式化查询时,不再省略此类变更的值。此前,精心构造的 AST JSON 负载可以用false执行某个Bool设置,而system.query_log和formatQueryFromJSON中显示的却是无值形式。#113025 (alexey-milovidov)。 - 修复了当
VIEW声明的列类型与其内部查询产生的类型不一致时,从该视图查询会报UNKNOWN_IDENTIFIER的问题,例如SELECT sum(length(arr)) FROM v,其中v基于一个String列声明了arr Array(UInt8)。在默认设置optimize_functions_to_subcolumns = 1下,优化器会将length(arr)重写为读取arr.size0子列,并将该名称传递给内部查询,而内部查询中并不存在该子列。#113057 (groeneai)。 - 修复了
postgresql表函数及 PostgreSQL 引擎读取操作的取消问题。若在读取仍处于启动阶段时取消,可能会在事务指针上产生竞争,且取消操作可能完全丢失,导致查询一直运行到 PostgreSQL 执行完毕。若取消请求在COPY语句开始执行之前就到达 PostgreSQL,仍有可能被丢弃。#113150 (groeneai)。 - 修复了基于集群表函数 (
s3Cluster、urlCluster、fileCluster) 的SQL SECURITY DEFINER或SQL SECURITY NONE视图作为二级查询被读取时 (例如通过remote或clusterAllReplicas) 出现的LOGICAL_ERROR(Next task callback is not set for query) 。现在这种不受支持的嵌套会以普通查询错误的形式被拒绝,而不会在 debug 和 sanitizer 构建中导致服务器中止。#113371 (groeneai)。 - 修复了在
analyzer_compatibility_join_using_top_level_identifier = 1时,将带有view(...)参数的 remote 系列表函数用于JOIN ... USING(其键为SELECT列表别名) 左侧时出现的逻辑错误IDENTIFIER is not a table expression。#113400 (groeneai)。 - 修复了查询在
indexHint中使用子查询对system.databases的name列进行过滤时出现的Not-ready Set is passed as the second argument for function 'in'错误,例如SELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo'))。此前,此类查询在 release 构建中会因LOGICAL_ERROR被拒绝,在 debug 和 sanitizer 构建中则会导致服务器中止。#113556 (groeneai)。 - 修复了针对
Variant列的查询会忽略max_execution_time和KILL QUERY的问题。调用带有多个Variant参数的函数时,会针对每个参数的每个备选类型分别解析一次函数,而执行这项工作的两个循环均未检查取消状态,因此此类查询在执行完毕之前无法被终止。#113612 (groeneai)。 - 修复了当同一条语句既将
ALIAS列转换为物理列 (DEFAULT或MATERIALIZED) 又指定CODEC时,ALTER TABLE ... MODIFY COLUMN失败并报错Cannot specify codec for column type ALIAS的问题。#113853 (groeneai)。 - 修复了使用常量
ON表达式与包含ARRAY JOIN的右侧进行连接时导致服务器崩溃的问题。原因是读取延迟复制的右侧列时使用了已被释放的ColumnReplicated。#113901 (groeneai)。 - 修复了在
optimize_aggregation_in_order = 1时,若表的 sorting key 是GROUP BY键的严格前缀,且使用了状态持有堆内存的聚合函数 (例如quantileDD) ,会出现内存泄漏的问题。此前每执行一次此类查询,服务器内存都会持续增长,直到重启为止。#114010 (groeneai)。 - 修复了
isProbablePrime在处理UInt128/UInt256时忽略max_execution_time和KILL QUERY的问题。此前,一个宽数值数据块会在单次函数调用中一直运行到结束,中间没有任何取消检查点,导致查询在超过截止时间后仍可能持续运行数分钟。#114032 (groeneai)。 - 修复了当
PREWHERE子句包含IN (subquery)谓词,且设置了rewrite_in_to_join = 1(或会强制启用该设置的make_distributed_plan = 1) 时,抛出Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION)的问题。而改用WHERE编写的相同查询此前即可正常运行。#114067 (RohithPariki)。 - 修复了当参数为元素类型是
Nothing的非空数组时,arrayAutocorrelation出现LOGICAL_ERROR的问题,例如SELECT arrayAutocorrelation([arrayMax([])])。现在此类参数会被拒绝,并报ILLEGAL_COLUMN错误。空数组字面量[]仍返回[]。#114249 (groeneai)。 CREATE TABLE和ALTER TABLE现在会拒绝在 sorting key 所用的列上使用SZ3等有损编解码器。#114531 (groeneai)。- 修复了当时间间隔参数以秒计的跨度为 2^32 的倍数时 (例如
toIntervalDay(2147483648)) ,函数hop和windowID陷入无限循环且无法取消的问题:回绕后的减法结果绕过了时间溢出检查;而当参数为常量时,该循环会在分析阶段执行,此时查询甚至无法被终止。同样的时间间隔还可能导致WINDOW VIEW的后台线程无休止地空转;现在此类 window view 会在创建时被拒绝。#114607 (alexey-milovidov)。 - 修复了包含从远程集群读取数据的
IN子查询的查询报出逻辑错误Not-ready Set is passed as the second argument for function 'in'的问题:现在该查询会返回子查询的实际错误,例如连接失败。#114983 (alexey-milovidov)。 - 修复了向
Log、TinyLog或StripeLog表执行INSERT时,在提交已记录的文件大小阶段失败的问题。此前,此类插入即使已报错,其行仍可能保留在表中,或导致数组列的各个数据文件彼此不一致。现在,若读取的Log或TinyLog表中某数组列不含任何元素,而其偏移量却表明存在元素,系统会抛出指明该列名称的错误,而不再越过元素末尾继续读取。对于部分写入的元素列,此前就已会予以拒绝。#115027 (groeneai)。 - 修复了包含
Array(Map(...))类型常量 (例如has([map('k', 'v')], m)) 的查询在Distributed表上执行或启用并行副本执行时,出现TYPE_MISMATCH(“CAST AS Array can only be performed between same-dimensional array types”) 错误的问题。#115883 (alexey-milovidov)。 - 修复了与视图或
view()进行连接时结果错误的问题:当其投影列与其自身某个内部关系的列同名时会触发该问题,例如SELECT expr(x.c0) AS c0 FROM a AS x, b AS y。连接顺序优化器会将此类表达式合并到展平后的连接图中,随后又将其应用了两次,导致查询在无任何提示的情况下返回有偏差的值。若该表达式还改变了列类型,同一原因则会在生成计划时引发AMBIGUOUS_COLUMN_NAME错误。#116152 (groeneai)。 - 修复了在使用 ROLLUP/CUBE 且启用
group_by_use_nulls时,外部列变为Nullable导致关联子查询抛出异常的问题。#100365 (alexey-milovidov)。 - 在
Replicated数据库上拒绝max_replication_lag_to_enqueue = 0。该值会使恢复后的未同步检查恒为真,并在 debug 和 sanitizer 构建中因LOGICAL_ERROR导致服务器中止。现在,无论来源为何 (CREATE DATABASE ... SETTINGS、<database_replicated>服务器配置块、ATTACH重放,以及升级时对现有元数据的重放) ,0都会在解析阶段被拒绝并报告BAD_ARGUMENTS。最小有效值为1。#106006 (groeneai)。 - 禁止在 JSON (Object) 列上创建 minmax 跳数索引,以避免插入混合类型数组时出现 NO_COMMON_TYPE 异常。请改用带类型的子列 (例如
INDEX idx json.field TYPE minmax) 。#106094 (linhaojie)。 - 修复了
JSON_QUERY/JSON_VALUE/JSON_EXISTS在参数为 Dynamic 类型时返回 Dynamic 而非 String/UInt8 的问题。#106877 (Avogar)。 - 修复了将等待超时类设置 (例如
interactive_delay) 设为极大值时发生的有符号整数溢出问题:此时等待可能立即超时,而非正常等待;在 Undefined Behavior Sanitizer 下,服务器还可能中止运行。#106961 (groeneai)。 - 修复了
geohashesInBox函数在坐标参数混用常量与非常量值,或坐标为BFloat16时出现的LOGICAL_ERROR(“Unsupported argument types”) 。现在,常量/非常量混用的Float32参数可以正常工作,而BFloat16参数会被拒绝并给出明确的错误信息。#107063 (groeneai)。 - 修复了启用
output_format_csv_serialize_tuple_into_separate_columns(默认启用) 时,CSVWithNames和CSVWithNamesAndTypes的表头列数少于数据列数的问题。现在,表头 (以及类型行) 会将Tuple列展开为以点号命名的叶子字段 (例如t.a、t.b) ,使表头列数与数据一致。新增设置output_format_csv_header_serialize_tuple_into_separate_columns(默认值为1) 用于控制该行为,将其设为0即可恢复此前的单一名称表头。#107371 (groeneai)。 - 修复了内置
mongo-c-driver中的内存泄漏问题:从 MongoDB 读取数据时 (例如通过 MongoDB 字典或mongodb表函数) ,若发生可重试的读取错误,且随后重试时的服务器选择失败,就可能出现该泄漏。#107448 (groeneai)。 - 修复了当
pointInPolygon使用Variant或Dynamic等包装类型的常量多边形参数调用时 (例如pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))) ,在主键分析期间出现的逻辑错误 (WhichDataType(const_type).isArray()) 及服务器中止问题。#107589 (groeneai)。 - 修复了因嵌套在
Variant和Dynamic列中的LowCardinality剥离不一致而导致的逻辑错误 (Bad cast) ,该问题会出现在concat、format以及主键分析等场景中。#107773 (Avogar)。 - 修复了可执行用户自定义函数命令参数的解析问题,名称为空或无效的占位符将不再被视为有效参数。#107983 (goutamadwant)。
- 修复了对元素为
Dynamic/Variant的Tuple执行accurateCastOrNull时,源数据中真正的NULL被误判为转换失败的问题。对于Nullable目标元素,源NULL现在保留为元素级NULL(与普通Tuple(Nullable(...))源的行为一致) ;对于非Nullable目标元素,源NULL现在会使整个元组变为 NULL (与非Dynamic参考实现的行为一致) ,而不再生成该元素的默认值。解析/溢出失败仍会使整个元组变为 NULL。#108023 (groeneai)。 mongodb表函数现在支持以命名参数形式传入oid_columns(例如oid_columns='_id') ,不再报BAD_ARGUMENTS错误。#108039 (alexey-milovidov)。- 现在可以对使用
DateTime64、Decimal或浮点范围的range_hashed或complex_key_range_hashed字典,传入类型匹配的参数调用dictGet/dictHas进行查询。此前此类查询会报must be convertible to Int64错误,且Decimal/DateTime64范围的开放区间会错误地返回默认值。#108052 (alexey-milovidov)。 - 修复了使用
accurateCastOrNull将Array(Dynamic)或Array(Variant)转换为QBit时导致的服务器中止问题 (IColumn::insertFrom中的Logical error) ,例如accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)')。#108288 (groeneai)。 - 修复了格式错误或不同步的原生 TCP 协议数据流可能引发的服务器崩溃 (
Received signal 4,非法指令) 。现在会在解析ClientInfo的initial_address字段之前,先校验其是否为数字形式的host:port,从而避免非数字端口被传入会触发陷阱的 libc 函数getservbyname。#108410 (groeneai)。 - 修复了反序列化
mannWhitneyUTest、rankCorr、largestTriangleThreeBuckets、quantileGK、sequenceMatch/sequenceCount和groupArrayIntersect的恶意构造聚合函数状态时内存分配过多的问题。格式错误的状态可能声明一个极大的元素数量,导致服务器仅凭几个字节的输入就尝试分配数十 GB 内存;现在此类状态会被拒绝,并报TOO_LARGE_ARRAY_SIZE错误。#108465 (groeneai)。 - 修复了在
GROUPING SETS/ROLLUP/CUBE中将group_by_use_nulls与LowCardinality常量分组键配合使用时出现的逻辑错误 (Bad cast from type DB::ColumnNullable to DB::ColumnString) 以及可能返回错误结果的问题。#108771 (alexey-milovidov)。 - 修复了当
Map值包含带有LowCardinality的嵌套Map时,mapFilter、mapSort、mapReverseSort、mapPartialSort和mapConcat报TYPE_MISMATCH错误的问题,例如mapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y')))。#108798 (groeneai)。 - 修复了在格式化混合具名与匿名元素的
Tuple数据类型 (例如Tuple(a UInt8, UInt16)) 时出现的LOGICAL_ERROR(“Inconsistent AST formatting”) ,该错误会导致 debug 和 sanitizer 构建中的服务器异常中止。#108915 (groeneai)。 JSONExtract在将字符串类型的 JSON 值转换为DateTime/DateTime64时,现在会遵循cast_string_to_date_time_mode设置,与CAST的行为保持一致。#109252 (Utkal059)。- 修复了
IN右侧参数为裸数组列时静默返回错误结果 (始终为 false) 或抛出异常的问题,现在x IN arr的行为与has(arr, x)一致。#109416 (alexey-milovidov)。 - 修复了
arrayFold作用于非常量Array(LowCardinality(T))参数时出现的LOGICAL_ERROR(例如arrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))) ,此前会报错 “Arguments of ‘plus’ have incorrect data types” (在 debug 和 sanitizer 构建中会导致服务器异常中止) 。#109462 (groeneai)。 - 通过将
FixedString参数正确转换为String,修复了conv中的ILLEGAL_COLUMN异常。#109771 (hp77-creator)。 - 修复了在
serialize_query_plan = 1下使用FINAL/SAMPLE读取表函数时返回错误结果的问题,并修复了表函数的聚合哈希表统计缓存键 (此前所有表函数共用同一个预分配条目) 。#109847 (azat)。 - 修复了在容器类型 (例如
Array(Bool)、Tuple(Bool, ...)) 中无法将数值1/0解析为Bool值的问题。此前[1,0]会报错CANNOT_READ_ARRAY_FROM_TEXT,而[true,false]则可以正常解析。#109976 (groeneai)。 - 修复了在
Array(LowCardinality(Nullable(String)))(包括以此方式存储的Nested字段) 上构建text索引、且被索引的数组包含NULL元素时出现的NOT_IMPLEMENTED错误 (Method getDataAt is not supported for Nullable(String) in case if value is NULL) 。现在构建索引时会跳过NULL数组元素,与Array(Nullable(String))的行为一致。#110055 (groeneai)。 - 修复了
subBitmap、bitmapSubsetInRange和bitmapSubsetLimit在 bitmap 仍处于小型表示时返回错误结果的问题,其中包括大于2^32的UInt64和Int64元素值被截断为 32 位的问题。bitmap 函数在有符号元素类型上的比较现在统一使用该元素类型的无符号值,因此在Int8bitmap 中,元素-1会按255进行比较,而不是按符号扩展后的4294967295比较;这同时修复了bitmapMin、bitmapMax、bitmapContains和bitmapTransform在已超出小型表示的 bitmap 上的行为。传入符号扩展阈值的查询需要相应调整:对于Int8bitmap,bitmapSubsetInRange(bm, 4294967168, 4294967296)应改为bitmapSubsetInRange(bm, 128, 256)。此外还修复了groupNumericIndexedVector在Int8和Int16索引列上返回的结果与更宽索引类型不一致的问题,以及numericIndexedVectorGetValue对负索引返回0的问题。更正了 bitmap 函数文档,包括子集函数被误称为使用从 1 开始的索引,以及有符号bitmapBuild/bitmapToArray的支持说明。#110072 (RamiDarwiche)。 - 修复了时间间隔运算中存在未定义有符号溢出的代码路径,涉及时间间隔类型的
WITH FILL STEP,以及增量取极端值时的add*/subtract*日期/时间间隔函数,使极端时间间隔值的结果具有确定性,不再依赖有符号溢出。同时修复了时间间隔类型的WITH FILL在YEAR步长极大时卡住的问题,此前该问题会导致日历倒退。#110158 (groeneai)。 - 修复了按序聚合在按多个键分组、且排序顺序仅为分组键前缀时,耗时呈二次方级增长 (且不响应
max_execution_time) 的问题。#110159 (alexey-milovidov)。 - 修复了操作数不存在最小共同超类型时,比较操作抛出
ILLEGAL_TYPE_OF_ARGUMENT的问题。Array(Int64)与Array(UInt64)、Array(Int256)与Array(UInt256)等数组现在可以使用=、!=、<、<=、>、>=、IS DISTINCT FROM和IS NOT DISTINCT FROM按字典序进行比较。isDistinctFrom/isNotDistinctFrom等 NULL 安全比较现在也会对受支持的非数组数值或十进制类型对按值进行比较,而不再抛出异常。包含嵌套Tuple(Nullable(...))元素的数组现在也支持相等比较。#110245 (diegomestre2)。 - 修复了在负偏移量时区中将极端
DateTime64值 (例如INT64_MIN) 转换为Time/Time64时出现的有符号整数溢出问题 (UBSan) 。#110451 (groeneai)。 - 将超出范围的浮点数值 (
BFloat16、Float32、Float64) 以及大于Int64::max()的UInt64值转换为DateTime和Time时,现在在所有架构上都会可靠地饱和到范围边界 (此前超出范围转换的结果取决于架构,在 x86-64 上可能发生回绕) ;非有限值 (NaN、inf) 现在会抛出异常,而不再产生任意结果。同样的修复也应用于toDate中浮点数到Date的转换路径,以及UInt64和宽整数 ((U)Int128、(U)Int256) 到Date和Date32的转换,这些转换此前可能返回纪元之前的日期,而非饱和到边界。将数字转换为Time时,现在对所有数值源类型都会饱和到该类型的范围 (此前来自窄无符号整数或宽整数的值在存储时未被限制在范围内,仅在打印时才进行钳制) ;精确转换为Time时不再拒绝Time所支持的负值,也不再对超出其范围的值静默饱和。将数字精确转换为Date32(accurateCast、accurateCastOrNull) 时,不再对超出范围或非有限的值静默饱和,而是与Date和DateTime的现有行为一致,抛出异常或返回NULL;对于此类输入,OrDefault变体会返回Date32的默认值。将非整数浮点数精确转换为Date、Date32、DateTime或Time时,现在会直接拒绝,而不再静默截断。此外还修复了toDateTime32函数的文档,该文档此前错误地展示了toDateTime64的示例,并描述了DateTime64的取值范围。#110459 (alexey-milovidov)。 - 修复了读取 map 键采用字典编码的 ORC 文件时,schema 推断因
Map cannot have a key of type LowCardinality(Nullable(String))而失败的问题,受影响的文件包括由 Spark 写入的 ORC 文件,以及 ClickHouse 自身在启用output_format_orc_dictionary_key_size_threshold时写入的文件。#110492 (tiandiwonder)。 - 修复了启用
optimize_or_like_chain时,若OR条件链中LIKE/ILIKE/match的左侧出现聚合函数或窗口函数,可能引发的逻辑错误 (Function node with name '...' is not resolved as ordinary function) 。#110641 (groeneai)。 - 修复了对
Date/Date32/DateTime64值使用极端的MONTH、WEEK或DAY时间间隔数调用toStartOfInterval时出现的有符号整数溢出问题。#110688 (groeneai)。 - 修复了
readWKT和readWKTPoint在处理POINT EMPTY时返回未初始化坐标 (标量版本) 或前一行残留坐标 (向量化版本) 的问题。现在POINT EMPTY会因CANNOT_PARSE_TEXT被拒绝,因为 ClickHouse 的Point是固定的Tuple(Float64, Float64),不存在空值表示。#110692 (groeneai)。 - 修复了
flipCoordinates丢失Geometry类型的问题:对于Geometry参数,结果类型现在恢复为Geometry,而不是底层的Variant(...),因此可以直接传递给areaCartesian等函数。#110694 (groeneai)。 - 修复了空多边形的 WKB 序列化结果不规范的问题:
wkb(POLYGON EMPTY)现在输出numRings = 0,而不再输出一个多余的零点环,从而使标准空多边形经 WKB 往返转换后能够无损还原。#110796 (groeneai)。 - JSON
Bool解析中的数值1/0现在会遵循allow_special_bool_values设置。此前,即使设置了allow_special_bool_values_inside_variant = 0,针对Variant(Bool, UInt32)的 JSON 输入 (如{"v":1}) 仍会被读取为Bool,原因是 JSONBool解析器忽略了该设置,而Bool的Variant反序列化优先级又高于整数类型。#110835 (groeneai)。 - 修复了当
col为LowCardinality时,throwIf(notLike(col, pattern))(以及其他作用于函数结果的throwIf) 会无条件抛出异常的问题。默认的LowCardinality实现会对整个字典执行throwIf,而该字典始终包含一个保留的默认值,即使没有任何行引用它;因此,只要这个未使用槽位中的值非零,throwIf就会在数据并不满足条件时抛出异常。#110864 (groeneai)。 - 修复了带有
-Tuple组合器的聚合函数与RESPECT NULLS一起使用并生成中间状态 (-State、分布式聚合、WITH ROLLUP/WITH CUBE) 时发生崩溃的问题。组合后的函数使用了错误的状态变体名称,导致其序列化后的AggregateFunction类型在往返转换时被重新解析为不兼容的内存布局。#110930 (groeneai)。 - 修复了通过
mysql表函数或MySQL表/数据库引擎读取可为空的 MySQL 空间列 (LINESTRING、POLYGON、MULTILINESTRING、MULTIPOLYGON、MULTIPOINT或通用的GEOMETRY) 时报错Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT)的问题。此类列现在会回退为Nullable(String),按 MySQL 返回的原样保存值 (4 字节 SRID 前缀加上 WKB 负载) 。POINT仍映射为Nullable(Point)。#110943 (groeneai)。 - 修复了与旧版本对端通信时,包含带版本聚合状态的
SimpleAggregateFunction包装器的Native序列化问题。#110997 (groeneai)。 - 修复了在分布式查询和使用并行副本的查询中,
Variant类型 (包括Geometry) 的常量出现CANNOT_CONVERT_TYPE错误的问题。#111136 (fm4v)。 - 修复了当高阶函数的 lambda 主体是条件为常量的
if/multiIf,且同时包含Bool字面量分支和UInt8比较分支时出现的LOGICAL_ERROR(“Lambda resolved type … is not equal to type from actions DAG …”) ,例如arrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL'])。#111245 (groeneai)。 - 修复了
toStartOfInterval使用亚秒级时间间隔时的有符号整数溢出问题:对于与Int64下界相差不足一个时间间隔的DateTime64值,舍入结果会静默回绕成一个无意义的正值;现在该函数会抛出DECIMAL_OVERFLOW异常。#111370 (alexey-milovidov)。 - 修复了在分布式查询中,在嵌套组合器下将
-Tuple组合器与RESPECT NULLS/IGNORE NULLS修饰符一起使用时抛出异常 (CANNOT_CONVERT_TYPE或逻辑错误) 的问题,例如anyRespectNullsStateTuple(...) IGNORE NULLS。#111570 (alexey-milovidov)。 - 修复了
FixedString文本尝试解析在解析失败时会在列中残留部分已追加字节的问题。该问题可能导致在对Variant/Array/Nullable列进行序列化时出现Sizes of nested column and null map of Nullable column are not equal逻辑错误,或导致结果字节被静默错位。#111908 (groeneai)。 - 修复了通过
Buffer表读取动态子列 (JSON或Dynamic列中的某个路径) 时抛出异常以及数据被静默跳过的问题。#111948 (alexey-milovidov)。 - 修复了
countSubstringsCaseInsensitiveUTF8的二次复杂度问题:此前在处理几 MB 大小且匹配项众多的 haystack 时,该函数需要耗时数分钟。现在每个匹配项的字符偏移量以增量方式维护,不再从行首重新计数。#112003 (groeneai)。 - 修复了
toStartOfInterval三参数重载中的有符号整数溢出问题:当origin参数接近Int64下界时,函数会返回回绕后的值,而不是报错。#112045 (alexey-milovidov)。 - 禁止在表函数参数中使用聚合状态,因为该用法完全不受支持。#112087 (PedroTadim)。
- 修复了
values表函数将插入到String/文本列中的非字面量Bool常量 (例如CAST(true, 'Nullable(Bool)')) 渲染为1/0而非true/false的问题。#112308 (yakov-olkhovskiy)。 - 修复了对某列应用
finalizeAggregation时出现的逻辑错误 (在 debug 和 sanitizer 构建中会导致中止) :当该列的聚合状态来自不同函数,且这些函数共享同一状态表示、但最终化后的类型不同时,就会触发该错误——例如通过UNION合并或经由arrayReduce生成的quantileState与quantilesState(0.9)。此类查询现在会抛出普通错误,而不再崩溃。#112662 (zainulabidin302)。 - 修复了
Poco::NumberParser(用于读取 JSON 数字) 在解析超出目标类型范围的整数时的问题。此前此类数字不会被拒绝,而是被静默解析为错误的值 (例如18446744073709551617变为1) ;此外,大于Int64最大值的UInt64数字在 AST JSON 往返转换后无法保持原值。#112904 (alexey-milovidov)。 - 修复了
IN右侧的Bool常量在针对String类型的左侧进行转换时,被转换为'1'/'0'而非规范形式'true'/'false'的问题 (现已与CAST和values表函数保持一致) 。#113051 (yakov-olkhovskiy)。 - 修复了
viewIfPermitted的 AST 格式化不一致问题:一是在表函数形式的ELSE分支中,通常以运算符形式书写的函数 (例如not) 格式化不一致;二是表达式形式viewIfPermitted(...)被错误地格式化为带有ELSE。#113652 (alexey-milovidov)。 - 修复
avg作用于Date/DateTime/DateTime64/Time/Time64时的未定义行为和错误结果:现在平均值在整数空间中精确计算,同时修复了Int64边界溢出问题 (未定义行为,在 x86 上会产生错误结果) 以及数值超过 2^53 时的Float64精度损失问题 (在纳秒尺度下可见) 。#113912 (alexey-milovidov)。 - 修复 Experimental
SZ3压缩编解码器中的内存泄漏:在压缩难以压缩或已损坏的数据时,如果因异常而失败,临时缓冲区不会被释放。#113916 (alexey-milovidov)。 - 修复使用
FixedString常量查询bloom_filter索引时,hasAny、hasAll、has、indexOf、mapContainsKey、mapContainsValue和mapContains返回行数过少或因TOO_LARGE_STRING_SIZE而失败的问题。原因是索引对常量填充后的形式进行哈希,而函数比较的是未填充的形式,导致本应匹配的 granule 被跳过。#114089 (alexey-milovidov)。 - 修复聚合经过 JIT 编译且数据包含 1970 年之前的时间戳时,
DateTime64列上的min和max返回错误结果的问题。DateTime64和Time64派生自Decimal64,但is_signed未针对二者进行特化,导致生成的代码将 tick 计数按无符号整数比较,使 1970 年之前的时间戳在max中被误选、在min中被漏选。#114168 (groeneai)。 - 修复数组元素与 needle 的字符串类型不同时 (例如用
String类型的 needle 匹配Array(FixedString(N))的元素) ,arrayExists(x -> x = needle, arr)返回错误结果或因TOO_LARGE_STRING_SIZE而失败的问题。默认启用的optimize_rewrite_array_exists_to_has优化会将此类调用改写为has,而has不会像=那样按零填充方式进行比较。#114496 (groeneai)。 - 修复作用于 Map 或 JSON 容器的
LIKE/ILIKE运算符在文本索引求值时的问题。#114544 (ahmadov)。 - 修复
quantile和quantiles在处理DateTime64和宽Decimal值时的未定义行为及边界结果错误。#114919 (alexey-milovidov)。 - 修复
Time分支与Time64、DateTime或DateTime64组合且表达式经过 JIT 编译时,if和multiIf返回一个很大的正值而非负值的问题。#115146 (groeneai)。 - 修复
timezoneOffset(别名timeZoneOffset) 返回的偏移恰好相差一天的问题。该问题出现在当前 UTC 偏移与 1970-01-01 时的偏移相差整整一天的时区 (例如跨越国际日期变更线之后的Pacific/Kiritimati和Pacific/Apia) ,以及大多数时区在 1970 年之前的时间。此修复同时修正了依赖该偏移的parseDateTime、parseDateTimeOrNull、parseDateTime64、parseDateTimeInJodaSyntax、EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...)、formatDateTime的%z、toUTCTimestamp和fromUTCTimestamp。#115332 (groeneai)。 - 修复了当
has或notHas谓词包含 NULL 数组元素,且主键为String、Array(String)或Map(String, String)时报错Code: 349. Cannot convert NULL value to non-Nullable type的问题;同时修复了当该元素为值为 NULL 的Dynamic或Variant时返回错误结果的问题。现在,键分析过程中会将 NULL 从集合中剔除,与其他键类型的现有处理方式一致。#115647 (groeneai)。 - 修复了当目标类型为
LowCardinality时,cast_keep_nullable未能保留可空性的问题。此前,将可为 NULL 的值转换为LowCardinality(T)时会抛出CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN错误,而非得到LowCardinality(Nullable(T))。#115851 (groeneai)。
索引与查询缓存问题修复
- 修复了读取子列时的问题:当某列具有
DEFAULT表达式且在某个分片中尚未物化时 (例如在ALTER TABLE ADD COLUMN之后,或在ALTER TABLE MATERIALIZE COLUMN执行期间) ,其子列会被填充为类型默认值,而不是DEFAULT表达式的计算结果;此外,在此类QBit列上调用转置向量距离函数 (cosineDistanceTransposed等) 会因SIZES_OF_ARRAYS_DONT_MATCH错误而失败。#110636 (alexey-milovidov)。 - 修复了
Not-ready Set is passed as the second argument异常:如果在主键分析期间构建IN子查询集合时静默失败 (例如在overflow_mode = 'break'下子查询超时) ,该集合在查询管道中会一直处于未构建状态,进而引发此异常。#107924 (alexey-milovidov)。 - 修复了在带有
set数据跳过索引的表上,当行策略使用恒为真的条件并结合对非索引列的检查进行过滤时,SELECT因NOT_FOUND_COLUMN_IN_BLOCK而失败的问题。#107971 (tiandiwonder)。 getClientHTTPHeader现在会被正确识别为非确定性函数,其结果不会再被查询结果缓存错误复用。#108029 (alexey-milovidov)。- 修复了查询条件缓存 (
use_query_condition_cache = 1) 将基于跳过索引得出的标记排除结果复用于运行了不同跳过索引集合的查询时,导致结果错误的问题,例如使用use_skip_indexes = 0、ignore_data_skipping_indices或不同的use_skip_indexes_for_disjunctions模式时。现在,基于跳过索引得出的缓存条目以实际运行的跳过索引集合作为键,而行级查询条件缓存条目在上述各种情况下仍可复用。#108548 (groeneai)。 - 修复了一个挂起问题:通过文件系统缓存读取数据的查询在被
KILL QUERY取消后,仍可能一直等待正在进行的下载;此外,如果可刷新materialized view 的刷新卡在此类等待中,删除该视图或对其执行SYSTEM STOP VIEW会被阻塞。#109116 (murphy-4o)。 - 修复了对于带有反向 (
DESC) 键列的表,当分片没有最终标记时 (非自适应粒度,index_granularity_bytes = 0) ,主键索引错误裁剪 granule 而导致查询结果错误的问题。#109901 (nihalzp)。 - 修复了
IN (subquery)中子查询包含关联子查询、且集合在索引分析期间构建时出现的逻辑错误Expected CommonSubplanReferenceStep to reference CommonSubplanStep、错误Subplan cannot be used to build pipeline以及逻辑错误Trying to extract chunk from ChunkBuffer before all inputs are finished。#110491 (alexey-milovidov)。 - 修复了启用并行副本时,使用标量子查询或常量参考向量调用
QBit列上的转置距离函数 (如cosineDistanceTransposed) 会出现NOT_FOUND_COLUMN_IN_BLOCK错误的问题。#110729 (alexey-milovidov)。 - 修复了文本索引的表达式包含空字符串比较 (如
arrayFilter(s -> s != '', ...)) 时该索引未被使用的问题,原因在于设置optimize_empty_string_comparisons只在查询侧将该比较改写为notEmpty。#112115 (Ergus)。 - 当某列同时在
PREWHERE和WHERE过滤条件中被引用时,即使该列被重写为文本索引虚拟列,也不再将其移除。#114460 (ahmadov)。 - 修复了在惰性 posting-list 应用模式下查询带有文本索引的表时,若查询在读取过程中被取消,会出现逻辑错误
Multi-block postings must be compressed的问题。#114636 (CurtizJ)。 - 修复了
WHERE子句中NOT内含NULL表达式时返回错误结果的问题,例如SELECT count() FROM t WHERE NOT (id >= 20 AND NULL)。索引分析会将此类条件判定为在整个范围内恒为真,从而跳过了过滤:count()返回了本应被查询排除的行,而使用该条件的ALTER TABLE ... DELETE则删除了本应保留的行。#115152 (groeneai)。 - 修复了在启用
query_plan_join_shard_by_pk_ranges的full_sorting_mergeJOIN 中,当某一侧因主键、列统计信息或表为空而被裁剪至不剩任何数据部分时出现的LOGICAL_ERROR(Join is supported only for pipelines with one output port) 。#115352 (alexey-milovidov)。 - 对基于 _part_starting_offset 的过滤器禁用查询条件缓存 #115358 (azat)。
- 修复了在带有隐式 minmax 索引 (
add_minmax_index_for_numeric_columns及相关设置) 的表上,单条ALTER TABLE语句同时包含RENAME COLUMN和其他命令 (如MODIFY SETTING) 时出现的LOGICAL_ERROR: Index with name auto_minmax_index_<column> already exists。此外,重命名普通列后,后续的DROP COLUMN不再因UNKNOWN_IDENTIFIER而失败,后续的ADD COLUMN也不会再缺失对应的隐式索引。#116063 (groeneai)。 - 不含通配符 (
%、_) 的LIKE/NOT LIKE模式现在会使用精确的主键范围,而非更宽的前缀范围,因此读取的粒度数量与等价的=/!=谓词相同。#107077 (groeneai)。 - 修复了当主键上的
IN/NOT IN条件用intDiv将键除以常量,且键为无符号整数、其取值跨越intDiv结果类型的有符号边界时 (例如intDiv(uint64_column, -9223372036854775807)) ,出现的LOGICAL_ERROR(Invalid binary search result in MergeTreeSetIndex) ,以及在发布构建版本中索引裁剪失效的问题。#107586 (groeneai)。 - 修复了
numericIndexedVectorPointwiseMultiply与 BSI 位配置不同的全 1 向量相乘时返回空结果的问题。#108027 (alexey-milovidov)。 - 修复了在包含大量不同短词元的数据上以
positions = 1构建文本索引时出现的堆缓冲区溢出 (heap-buffer-overflow) 问题。#108659 (groeneai)。 - 允许文本索引的
preprocessor和postprocessor表达式引用ALIAS列。#110014 (Ergus)。 - 使用
LIMIT ... WITH TIES时不再应用向量搜索优化,因为该优化会将 ANN 搜索限定为恰好 n 个候选结果,导致与第 n 行并列的行被丢弃。#110453 (tamish560)。 - 修复了当文本索引定义在表达式而非单纯的列上时 (例如带有
lower(...)预处理器的assumeNotNull(col)) ,ILIKE无法使用该文本索引的问题。此类查询现在会使用索引,不再读取全部粒度。#110595 (ahmadov)。 - 修复了在
vector_search_with_rescoring = 1与延迟物化同时启用且存在多个距离并列时,向量搜索查询可能出现的LOGICAL_ERROR(LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M) 。#111003 (groeneai)。 - 使用带
i8量化的vector_similarity索引时,拒绝平方模长溢出为无穷大的向量 (此前此类向量会在 usearch 中触发未定义行为,并静默产生无效数据) 。#111085 (groeneai)。 - 修复了启用页缓存时在
plain_rewritable磁盘上读取到过期数据的问题。#111105 (Michicosun)。 - 修复了
String(或更窄的FixedString) 键或 minmax 跳过索引与更宽的FixedString常量进行比较过滤时 (例如toFixedString('abc', 257) = string_col) ,count()结果错误且丢失行的问题。主键和 minmax 裁剪基于以 NUL 填充后的常量构建范围,因而错误地跳过了匹配的粒度。#111106 (groeneai)。 - 修复了读取偏移量索引不从第 0 行开始的 Parquet 文件时出现的问题。此类文件可能导致原生 Parquet 读取器返回错误的行,或报告
LOGICAL_ERROR而非INCORRECT_DATA。现在读取偏移量索引时会对其进行校验。#114530 (groeneai)。
安全、访问、备份与恢复相关修复
- 当目标端表启用了
fsync_after_insert时,RESTORE现在会对恢复的分片文件执行 fsync,使恢复的分片在应对断电时具备与插入的分片同等的持久性。此前,恢复的文件仅被写入并关闭 (从不执行 fsync) ,因此如果在RESTORE返回RESTORED后立即断电,可能导致分片损坏、表中数据为空。#111378 (groeneai)。 - 修复了一个安全问题:未经身份验证的 TCP 客户端可通过服务器间端口探测表是否存在及其复制状态。#99854 (tiandiwonder)。
- 修复了
DELETE FROM(轻量级删除) 除ALTER DELETE外还额外要求ALTER UPDATE特权的问题。现在,仅被授予ALTER DELETE的用户即可按文档所述运行DELETE FROM。#107491 (tiandiwonder)。 - 修复了在 Atomic 数据库上执行
CREATE TABLE ... AS SELECT时,若查询失败 (例如用户无权访问子查询中引用的表) ,会遗留一个空表的问题。此前重试时会报告表已存在,而非原始错误。现在该表会先以临时表的形式创建,待数据完全填充后才可见。#108048 (alexey-milovidov)。 - 修复了当用户仅被授予某个
ALIAS列的SELECT访问权限时,在该表上执行SELECT count()(或其他简单查询) 会报出LOGICAL_ERROR(No available columns) 的问题。#108056 (alexey-milovidov)。 - 修复了未经身份验证的请求可能导致 ClickHouse 解析转发客户端地址请求头中所提供主机名的问题。ClickHouse 现在仅接受这些请求头中的数字 IP 地址。在按转发地址进行配额归属时,无效值会被直接忽略,不会进行 DNS 解析。启用
auth_use_forwarded_address时,无效的转发地址会在身份验证阶段被拒绝。拒绝事件会以 debug 级别记录到日志中。#111060 (otselnik)。 - 修复了在禁用 analyzer (
enable_analyzer = 0) 时,参数化视图未遵循SQL SECURITY DEFINER(及SQL SECURITY NONE) 的问题。此前,不具备底层表特权的用户查询此类视图时会因ACCESS_DENIED而失败,而同一视图在启用 analyzer 时却能正常工作。#111458 (groeneai)。 - 修复了
MySQL集成中的一个缺陷:当命名集合以内容形式存储 TLS 凭证时,使用空的ssl_ca_pem/ssl_cert_pem/ssl_key_pem值覆盖该凭证会被接受,导致已配置的 CA 或客户端证书被静默丢弃,而不是拒绝此次覆盖。#113947 (alexey-milovidov)。 - 修复了对声明为
SQL SECURITY DEFINER或SQL SECURITY NONE且主体包含 JOIN 的视图执行EXPLAIN ANALYZE时丢失连接统计信息的问题。在 debug 和 sanitizer 构建中,该查询会因逻辑错误JoinStep analyzed without the analyze mode而中止。#115156 (groeneai)。 - 修复了
RESTORE ... AS <new name>后,可刷新materialized view 的REFRESH ... DEPENDS ON列表仍指向原始数据库的问题。恢复后的视图会因一个它已不再读取的表而触发刷新,却忽略其自身父表的刷新,并在原始数据库被删除后彻底停止刷新。#115689 (groeneai)。 - 修复了对正在被并发删除并重建的
Replicated数据库进行备份时出现的LOGICAL_ERROR异常;此类备份现在会以CANNOT_GET_REPLICATED_DATABASE_SNAPSHOT错误正常失败。#100651 (alexey-milovidov)。 - 对同一角色执行
GRANT role TO role时,现在会以BAD_ARGUMENTS错误拒绝执行,而不再静默地在system.role_grants中创建自引用条目。#103315 (zxuhan)。 - 对
MaterializedPostgreSQL数据库执行BACKUP时,不再因 “Table … were created or changed its definition during scanning” 而无限期卡住,并且现在会真正备份表数据 (交由底层的ReplacingMergeTree处理) ,备份数据可恢复为独立的ReplacingMergeTree表。#107433 (alexey-milovidov)。 - 允许仅对字典拥有
SHOW DICTIONARIES特权的用户执行EXISTS <dictionary>(此前需要SHOW TABLES特权) 。#108084 (alexey-milovidov)。 - 修复了
BACKUP ... TO Memory(...)在完成前失败时的清理问题:此前失败的备份会一直保持注册状态,导致其名称无法再次使用。#109947 (jkartseva)。 - 修复了
ReadBuffer is canceled. Can't read from it.逻辑错误 (在 debug/sanitizer 构建中会导致服务器中止) :如果此前对某个 zip 归档的读取在中途失败,之后再次读取该归档 (例如从 zip 备份执行RESTORE) 时可能触发该错误。#110197 (groeneai)。 - 修复了可能导致服务器在关闭时崩溃的堆损坏问题,其根源在于
const方法AccessRights::getFilters修改了由多个并发查询共享的访问权限树。#112692 (groeneai)。
分布式执行、表、视图和字典
- 修复了
ALTER TABLE ... MOVE PART ... TO SHARD '<path>'误报Inconsistent AST formatting错误的问题。查询格式化器会丢失SHARD关键字,导致格式化后的查询无法被重新解析,进而引发LOGICAL_ERROR(在 release 构建中表现为已处理的异常,在 debug 和 sanitizer 构建中则会直接中止) 。#109060 (groeneai)。 - 修复了以空远程数据库名定义的
Distributed表在distributed_product_mode = 'local'下参与 JOIN 时出现逻辑错误 (!part.empty()) 的问题。#110677 (groeneai)。 - 修复了当 DISTINCT 提前终止所用的 limit 提示无法限定结果头部范围时,带排序
LIMIT/OFFSET的DISTINCT返回错误行的问题,涉及以下情况:负数LIMIT(返回了头部而非尾部) 、小数LIMIT/OFFSET(小数需在完整读取后才能确定) ,以及不带LIMIT的单独OFFSET(偏移量之后的尾部数据被丢弃) 。例如,在包含多个 part 的表上执行SELECT DISTINCT intDiv(x, 100) FROM t ORDER BY intDiv(x, 100) LIMIT -1时,返回的是最小的去重值而非最大值。#111326 (groeneai)。 - 修复了 DESCRIBE TABLE 中子查询后的别名无法被解析器识别并导致语法错误的问题。修复 https://github.com/ClickHouse/ClickHouse/issues/100031。[#100205](https://github.com/ClickHouse/ClickHouse/pull/100205) (yariks5s)。
- 修复了在
DETACH DATABASE/ATTACH DATABASE之后,对于设置了lazy_load_tables = 1的Atomic数据库,在ALTER RENAME COLUMN执行期间并发INSERT可能导致服务器中止 (Logical error: 'Block structure mismatch') 的问题。#104852 (groeneai)。 - 修复了设置
inject_random_order_for_select_without_order_by导致的列名损坏和BAD_ARGUMENTS异常。启用该设置后,多列 SELECT 不会再失败,输出列名 (例如用于CREATE TABLE AS SELECT、CREATE VIEW AS SELECT、JSONEachRow时) 也会得到保留,而不会被替换为内部的__subquery_column_<UUID>别名。#105896 (groeneai)。 - 修复了服务器重启 (或执行
DETACH/ATTACH DATABASE) 后出现令人困惑的 “Maybe you meant X?” 提示的问题:删除一个已被删除的表时,系统会把刚刚删除的表名作为候选建议。现在分离时会从DatabaseOrdinary::startup_table和load_table中清除异步加载任务。#106238 (groeneai)。 - 修复了
MaterializedPostgreSQL表引擎和数据库引擎,使其支持从非默认的 PostgreSQL schema (materialized_postgresql_schema) 复制单个表或数据库,包括同一数据库的多个 schema 中存在同名表的情况 (此前这些表会共用同一个 publication 和 replication slot,导致相互干扰) 。#107425 (alexey-milovidov)。 - 修复了以下问题:使用并行副本的查询读取以
GLOBAL JOIN临时表形式传输的表中的ALIAS列时报NO_SUCH_COLUMN_IN_TABLE;分布式JOIN两侧都声明了同名ALIAS列时报MULTIPLE_EXPRESSIONS_FOR_ALIAS;以及Distributed表声明了基于另一个ALIAS列的ALIAS列 (包括将其用作JOIN USING键) 时报UNKNOWN_IDENTIFIER。#107700 (yakov-olkhovskiy)。 - 修复了当
refresh_retries设置为极大值 (接近Int64最大值) 时,可刷新materialized view重试失败的刷新会导致有符号整数溢出的问题。在启用未定义行为 sanitizer 的构建中,该溢出可能导致服务器中止。#108005 (groeneai)。 - 修复了加载使用复合键的字典时出现的异常 (
CANNOT_PARSE_TEXT) :当键列不是字典定义中的前几列,且使用带显式查询的本地ClickHousesource 时会触发该问题。现在源列按名称而非位置与字典结构进行匹配。#108053 (alexey-milovidov)。 - 修复了在不带
WHERE子句查询Hive表时 (例如SELECT * FROM hive_table) 发生的崩溃 (空指针解引用) 。#108094 (alexey-milovidov)。 - 修复了当分布式查询将尚未物化的
MATERIALIZEDCTE 作为外部表引用,且远程 source 为延迟创建 (delayed source) 时,可能发生的服务器崩溃 (段错误) 。该崩溃源于RemoteQueryExecutor::sendExternalTables()内部对空Logger的解引用。#108547 (groeneai)。 - 修复了对
STREAM读取执行DISTINCT(SELECT DISTINCT ... FROM table STREAM) 时出现的逻辑错误 (Equal values are not contiguous within the range assumed to be sorted) 。由于STREAM读取按提交顺序而非排序键顺序输出行,按序读取优化将不再应用于此类读取。#108568 (groeneai)。 - 修复了在
optimize_skip_unused_shards = 1时,若Distributed表的分片键是会被分析器常量折叠的表达式 (例如if(1, toInt32(id), toInt32(id) + 1)) ,会引发异常 (Cannot find sharding key column,在 debug/sanitizer 构建中则会导致服务器中止) 的问题。#108737 (groeneai)。 - 修复了通过
Alias表执行的INSERT ... SELECT在未抛出异常的情况下被取消时 (例如设置了timeout_overflow_mode = 'break') 导致服务器中止 (LOGICAL_ERROR/ debug 和 sanitizer 构建中的断言失败) 的问题。#108783 (groeneai)。 - 修复了向
TimeSeries表执行的INSERT ... SELECT在未抛出异常的情况下被取消时 (例如设置了timeout_overflow_mode = 'break') 导致服务器中止 (LOGICAL_ERROR/ debug 和 sanitizer 构建中的断言失败) 的问题。#108796 (tiandiwonder)。 - 修复了分布式查询偶尔因
UNEXPECTED_PACKET_FROM_SERVER(“expected TablesStatusResponse, got ProfileInfo”) 而失败的问题:当连接池复用了先前被取消的查询遗留下的、处于不同步状态的连接时,会触发该问题。#108854 (alexey-milovidov)。 - 修复了在针对
Distributed表的查询中,MATERIALIZEDCTE 在连接树的多个位置被引用时 (例如两个参与连接的子查询,或一个参与连接的子查询加上WHERE中的标量子查询) 出现的LOGICAL_ERROR(CTE '...' does not have query tree, but was not planned yet) 。现在该查询可以正常执行,不再抛出异常 (此前在 debug/sanitizer 构建中会导致服务器中止) 。#108924 (groeneai)。 - 修复了一个内存安全问题:由 materialized view 处理调度的异步任务,可能在查询结束后仍继续使用查询级别的资源统计。#108988 (filimonov)。
- 修复了一个
LOGICAL_ERROR(“Cannot find__grouping_setcolumn in header of MergingAggregatedTransform with grouping sets” 或 “Chunk info was not set for chunk in MergingAggregatedTransform”) 。在未启用分析器的情况下,对于UNION ALL/INTERSECT/EXCEPT查询,若其中一个分支在启用并行副本时使用GROUP BY GROUPING SETS,而另一个分支使用FINAL,则可能出现该错误。#109003 (groeneai)。 - 修复了在
Replicated数据库中执行CREATE TABLE ... AS SELECT FROM s3Cluster(...)(以及fileCluster/urlCluster等其他 cluster 表函数) 时因NOT_FOUND_COLUMN_IN_BLOCK而失败的问题。#109266 (groeneai)。 - 修复了在包含两个或更多分片的集群上执行读取
Distributed表的CREATE TABLE ... ON CLUSTER ... AS SELECT时出现的错误 (NOT_FOUND_COLUMN_IN_BLOCK,旧版本中为std::bad_function_call) 。#109407 (alexey-milovidov)。 - 修复了将表表达式用作
IN运算符左侧参数时出现的令人费解的内部错误 (Method getResultType is not supported for TABLE query tree node) ;此类查询现在会返回清晰的错误信息。#109412 (alexey-milovidov)。 - 修复了在
optimize_const_name_size取值较小时,对Distributed表执行SELECT ... ORDER BY ... WITH FILL出现的Bad cast from type DB::FunctionNode to DB::ConstantNode逻辑错误 (在 debug/sanitizer 构建中会导致服务器中止) 。#109938 (groeneai)。 - 修复了连接顺序优化器中的
LOGICAL_ERROR(Left and right columns have same names) 。在启用query_plan_merge_expression_into_join时,对多表视图执行逗号连接可能触发该错误。#110227 (groeneai)。 - 修复了带有
LIMIT的合法分布式查询偶发抛出Logical error: 'No more packets are available.'的问题,该问题会在 debug 和 sanitizer 构建中导致服务器中止。#110334 (groeneai)。 - 修复了一个解析器缺陷:当 SELECT 查询紧接在裸表标识符之后结束时 (例如
... FROM t COMMENT 'x') ,COMMENT 会被错误地解析为隐式别名,从而报出具有误导性的语法错误,而不是将注释应用到视图/表上。#110372 (adityaksolves)。 - 修复了一个结果错误:在启用并行副本且查询带有高选择性过滤条件时,对
FixedString列调用length()(以及 QBit 维度) 会返回0,而非固定长度N。#110427 (groeneai)。 - 修复了并行副本以
custom_key_sampling/custom_key_range模式运行时,FROM中包含子查询的查询报NOT_FOUND_COLUMN_IN_BLOCK错误的问题。此类查询 (例如SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k) 此前会因Not found column __table2.id in block ...而失败。#110690 (groeneai)。 - 修复了对包含流式 (
FROM ... STREAM) 读取的查询执行EXPLAIN ANALYZE时出现Logical error: 'clock'的问题 (在 debug/sanitizer 构建版本中服务器会崩溃;在发行版构建版本中则会无限挂起) 。该问题出现在流式读取并非简单的顶层表表达式时,例如嵌套在子查询中 (如位于WHERE ... IN (...)或 CTE 内部) ,或隐藏在普通视图或参数化视图之后。现在EXPLAIN ANALYZE会以NOT_IMPLEMENTED拒绝此类查询,与其对顶层流式读取的处理方式一致。#110935 (groeneai)。 - 修复了当表与其所在数据库同名时,analyzer 无法正确解析完全限定列名 (例如
db.table.column) 的问题。#110976 (alexey-milovidov)。 - 修复了在设置了
parallel_replicas_min_number_of_rows_per_replica且投影了左表列时,RIGHT JOIN报出NOT_FOUND_COLUMN_IN_BLOCK/THERE_IS_NO_COLUMN错误 (在某些发行版中则会静默返回错误结果) 的问题。#111332 (groeneai)。 - 修复了可执行 UDF、
executable表引擎和可执行字典中的竞态问题:对已关闭的文件描述符执行fcntl可能会破坏并发查询中某个无关的描述符 (清除其O_NONBLOCK标志) ,进而导致查询无限期挂起。#111779 (Algunenano)。 - 修复了对包含两个或更多分片的
Distributed表、clusterAllReplicas或基于自定义键的并行副本执行ORDER BY ... WITH FILL ... INTERPOLATE时 (包括结果为空的情况) 出现的LOGICAL_ERROR(“Invalid number of rows in Chunk”) 问题,以及在加固构建版本中与之相关的越界中止问题。现在WITH FILL仅在生成最终结果的节点上执行,这也一并修复了生成的填充行在各分片/副本间重复的问题。#111919 (yakov-olkhovskiy)。 - 修复了针对
system.replicas的查询在其状态请求处理前被终止时,DROP TABLE ... SYNC永久挂起的问题。#112164 (evillique)。 - 修复了多表连接中两个子连接均不产生输出列时抛出
LOGICAL_ERROR异常 (Block structure mismatch in joined block stream) 的问题,例如在query_plan_optimize_join_order_limit设置为0或1时执行SELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a)。#112205 (groeneai)。 - 修复了包含
FINAL、PREWHERE过滤条件、较小LIMIT且make_distributed_plan = 1的查询在所选列顺序与表的列顺序不同时出现逻辑错误Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStep的问题。原因是延迟物化在替换计划节点时未保留该节点的输出请求头,导致查询计划不一致。#112303 (groeneai)。 - 修复了使用旧 analyzer 时,若必须为常量的参数 (例如
toDecimal32的 scale 或toDateTime的时区) 来自标量子查询,会导致结果错误和逻辑错误的问题。此前此类参数在分析阶段会被当作零值或空值处理,致使声明的结果类型与实际计算值不一致,并导致CREATE VIEW和CREATE MATERIALIZED VIEW持久化错误的列类型。#112492 (groeneai)。 - 修复了普通
VIEW的定义通过查询参数引用表或字典时 (例如CREATE VIEW v AS SELECT x FROM {db:Identifier}.t) 出现的逻辑错误和依赖记录错误。此类视图不再对当前数据库中的同名表记录引用依赖,因此无关的表又可以正常删除了。#112704 (groeneai)。 - 修复了
Join表引擎用于 JOIN 右侧、且ON部分包含同时引用两张表列的条件时 (例如ON (t.key = j.key) AND (t.a < j.a)) 出现的逻辑错误。此类查询现在会被拒绝并给出明确的异常,而不再抛出required columns: ... but not found any in left table或std::bad_variant_access。#112815 (groeneai)。 - 修复了以极大延迟调度后台任务时 (例如可刷新materialized view 设置了极大的
REFRESH AFTER周期) 出现的未定义行为和静默调度错误。现在延迟会被限制在可表示的最大值以内,不再发生溢出。#113041 (groeneai)。 - 修复了向
Distributed表执行异步INSERT时,若所需队列目录名称超出文件系统 255 字节的限制 (在use_compact_format_in_distributed_parts_names = 0时可能出现) 所报告的错误。此前,对于启用internal_replication的分片会报告LOGICAL_ERROR,其他情况下则报告缺少来源信息的Code: 1001. std::exception;现在两种情况均报告ARGUMENT_OUT_OF_BOUND,并指明表名、集群和限制值。#113083 (groeneai)。 UNDROP TABLE在等待正在运行的查询释放已删除的表时,现在可以通过KILL QUERY中断。#113263 (alexey-milovidov)。- 修复了使用 materialized CTE 的查询失败后,
DROP TABLE永久挂起并发生内存泄漏的问题。此前该表会一直卡在删除队列中,直到服务器重启。#113397 (tiandiwonder)。 - 修复了在
make_distributed_plan下,子查询在自身的SETTINGS子句中设置distributed_plan_execute_locally时出现的段错误和LOGICAL_ERROR(No host found for exchange stream final_result__0_0) 。分布式查询计划与执行该计划的代码从两个不同的上下文读取该设置,二者可能不一致,导致发起节点构建出自相矛盾的管道。#113422 (groeneai)。 - 修复了启用
database_atomic_wait_for_drop_and_detach_synchronously时,若用于填充数据的SELECT失败,CREATE TABLE ... AS SELECT将无法被终止的问题:对临时表执行的内部清理DROP会等待后台删除队列,且会忽略KILL QUERY和max_execution_time。#113504 (groeneai)。 - 修复了启用
join_use_nulls时,对字典执行JOIN且ON子句包含涉及两张表的非等值条件 (例如ON (t.key = d.key) AND (t.a * 10 < d.a)) 时返回错误结果的问题,以及在启用断言的构建中触发断言中止的问题。此前该条件是基于以不匹配类型读取的列求值的,因此行可能被任意匹配。#113534 (alexey-milovidov)。 - 修复了以下问题:当以非限定名引用参数化视图的查询被发送到分片时,该视图会丢失其所属数据库,导致分片在自身的默认数据库中解析该名称。视该数据库中的内容而定,查询要么以
UNKNOWN_FUNCTION失败,要么静默返回另一个视图中的行。此问题影响通过Distributed表执行的IN、JOIN和remote()。#113550 (groeneai)。 - 修复了读取
Join引擎表时出现的Unsupported JOIN keys of type keys256 in StorageJoin错误,该问题出现在表的键为复合键 (多个列) 或单个 16/32 字节值 (例如UUID、Int256或FixedString(4)) 时。此类表此前可以创建、写入并参与连接,但始终无法通过SELECT读回数据。#113578 (groeneai)。 - 修复了逻辑错误
Sending a distributed query with unknown (zero) client version:该错误出现在挂载基于远程分片的无结构Distributed表,或从旧版本服务器写入的元数据中加载此类表时。#113675 (alexey-milovidov)。 - 修复了
SELECT对命名表使用STREAM修饰符、同时以读取任务模式启用并行副本时出现的LOGICAL_ERROR。当在PREWHERE中将 materialized CTE 用作IN集合时,服务器会抛出Reading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan(在 debug 和 sanitizer 构建中会导致服务器中止) 。现在,请求并行副本时将拒绝带有STREAM的表:当enable_parallel_replicas = 2时,查询以SUPPORT_IS_DISABLED失败;当其为1时,查询将不使用并行副本运行,与FINAL的现有行为完全一致。#113754 (groeneai)。 - 修复了解析
remote、mysql等表函数的地址参数时存在的二次复杂度问题:过长的地址 (例如兆字节级、以零填充的FixedString) 会使查询在分析阶段卡住,且无法取消。#113918 (alexey-milovidov)。 - 修复了在启用
database_atomic_wait_for_drop_and_detach_synchronously时,可刷新materialized view 的刷新被取消 (例如因服务器关闭) 后误报Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup.错误的问题。实际上临时表已被删除,根本无需手动清理。#113957 (groeneai)。 - 修复了在启用
materialized_views_ignore_errors时,materialized view 在收集依赖项期间失败后system.query_views_log中缺少对应行的问题。在 debug 和 sanitizer 构建中,这还会导致服务器因std::out_of_range中止,而非记录该视图。#114064 (groeneai)。 - 修复了右表非键列上的过滤条件被下推到 ANY INNER JOIN 之下时结果不一致的问题。#114313 (kirillshokhin)。
- 修复了在设置
ignore_drop_queries_probability时,CREATE OR REPLACE遗留内部_tmp_replace_*表,以及CREATE OR REPLACE VIEW以NOT_IMPLEMENTED失败的问题。其内部发出的 DROP 只是同一条用户语句中的步骤,因此 DROP 故障注入不再对其生效。#114420 (groeneai)。 - 修复了读取 Delta Lake 表时,若
metaData.partitionColumns中指定的列未在metaData.schemaString中声明,会导致LOGICAL_ERROR的问题。现在,只要从快照中读取该表或其 schema (而不仅限于查询带有谓词时) ,此类元数据都会被拒绝:delta-kernel 读取器返回BAD_ARGUMENTS,旧版读取器返回INCORRECT_DATA。#114538 (groeneai)。 - 修复了以下问题:当服务器启动后运行的第一个聚合查询使用了 lazy
FINAL优化 (query_plan_optimize_lazy_final) 时,哈希表统计信息 (连同依赖它的聚合哈希表预分配) 会在整个服务器范围内被静默且永久地禁用。#114597 (alexey-milovidov)。 - 修复了启用
ignore_drop_queries_probability时,可刷新materialized view 泄漏被轮换下来的 target table 的问题。刷新过程中为清理先前 target table 而发出的DROP属于刷新的一个步骤,而非用户发起的DROP,因此故障注入不再对其生效。#114622 (groeneai)。 - 修复了
ON子句中包含多个以OR连接的条件时,ANY RIGHT JOIN和SEMI RIGHT JOIN会将右表的部分行返回两次、同时丢失其他行匹配结果的问题。显式编写的ANY LEFT JOIN也受影响,因为规划器可能会交换两表并将其作为ANY RIGHT JOIN执行。#114676 (vdimir)。 - 修复了当查询中的
JOIN位于某个表之上,且该表的文本索引列同时被PREWHERE和WHERE文本搜索谓词使用时出现的LOGICAL_ERROR(Cannot find input column ... on its position in inputs of expression actions DAG) 。#114771 (groeneai)。 - 修复了对在
ALIAS或EPHEMERAL列上声明了STATISTICS(...)的表执行任何INSERT都会报NOT_FOUND_COLUMN_IN_BLOCK,从而导致此类表实际上变为只读的问题。#115231 (groeneai)。 - 修复了分布式查询中
dictGet及其变体的问题:未限定的字典名称现在绑定到发起服务器的当前数据库,而不再基于各分片的当前数据库进行解析——此前要么找不到该字典,要么解析到另一个同名字典。#115541 (alexey-milovidov)。 - 修复了以新名称恢复数据库或表时,已存储视图定义中的表别名被丢弃,导致读取恢复后的视图失败并报
UNKNOWN_IDENTIFIER的问题。#115645 (groeneai)。 - 修复了在基于
Distributed表的IN子查询内部读取MATERIALIZEDCTE 时出现的LOGICAL_ERROR“Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan”。#115740 (groeneai)。 - 修复了 DETACH DICTIONARY … PERMANENTLY 被依赖检查 (HAVE_DEPENDENT_OBJECTS) 拒绝后,dictGet 报 BAD_ARGUMENTS “Dictionary not found” 的问题。现在分离操作被拒绝时,该字典仍可完全正常使用。#105259 (groeneai)。
- 修复了后台表删除队列中的
Logical error: 'removed'(在 debug 构建中会导致服务器中止) 。当多个CREATE OR REPLACE TABLE查询重复使用同一个显式 UUID 时,会有多个共享该 UUID 的已删除表进入队列,从而触发此问题。#107031 (groeneai)。 - 修复了服务器停机期间单个复制表的结构发生变化时,
MaterializedPostgreSQL会停止整个数据库复制 (并报错LOGICAL_ERROR: Columns number mismatch) 的问题。现在仅会跳过受影响的表,且该表可通过DETACH/ATTACH恢复。#107427 (alexey-milovidov)。 - 修复了集群中存在非活动副本 (例如自动扩缩容后遗留的过期条目) 时,并行副本工作分配严重倾斜的问题。读取协调器不再将此类副本计入,因此工作会在在线副本之间均衡分配,而不会全部堆积到单个副本上。#107805 (alexey-milovidov)。
- 修复了多个在 XML 中定义的 MySQL 字典通过
share_connection共享同一个连接池时,SYSTEM RELOAD DICTIONARIES(以及RELOAD DICTIONARY) 卡死的问题。此类连接池现在会遵循配置中的connection_pool_size和connection_wait_timeout(默认 5 秒) ,与通过命名集合定义的字典行为一致。#108083 (alexey-milovidov)。 - 防止由 leader 执行的复制分布式 DDL 在重试次数耗尽后永久阻塞后续的
ON CLUSTERDDL 查询。#108505 (ahaanlimaye)。 - 修复了
SYSTEM FLUSH DISTRIBUTED与针对同一Distributed表的DROP TABLE并发执行时可能发生的崩溃 (释放后使用) 。#108684 (groeneai)。 - 修复了自动并行副本规划器中的
LOGICAL_ERROR(local_replica_plan_reading_step->getAnalyzedResult() == nullptr) ,该错误可能在启用automatic_parallel_replicas_mode且parallel_replicas_min_number_of_rows_per_replica大于 0 时出现。#109011 (groeneai)。 - 修复了非事务性
TRUNCATE与一个已向同一表插入数据但尚未提交的事务并发执行时,可能抛出的LOGICAL_ERROR(creation_csn is not set while removal_csn is set to 1) 。此类TRUNCATE不再删除由尚未提交的事务创建的数据分区片段。#109598 (tuanpach)。 - 外部数据库引擎 (例如
PostgreSQL) 不再下推针对UUID列的范围比较 (>=、>、<=、<) 。由于 ClickHouse 与外部数据库对 UUID 的排序方式不同,下推这些比较会导致结果中的行被静默丢弃;此类谓词现改由 ClickHouse 自行计算。#109833 (vismaytiwari)。 - 修复了
MaterializedPostgreSQL数据库引擎中,表在仍处于同步队列时被分离 (或其结构发生变化) 可能导致服务器崩溃的问题。#110596 (alexey-milovidov)。 - 修复了
EPHEMERAL列的类型会被服务器的query_masking_rules改写的问题。若某条规则匹配到类型内部的内容,会导致CREATE TABLE存储错误的类型,甚至执行失败。#112048 (alexey-milovidov)。 - 修复了表名长度检查中的无符号下溢问题,该问题会导致创建出永远无法删除的表。当转义后的数据库名称达到 214 字节时,为
metadata_dropped文件名计算的长度上限会发生回绕,导致CREATE TABLE被接受,而随后的DROP TABLE或DROP DATABASE却因File name too long而失败。现在此类名称会被拒绝并返回ARGUMENT_OUT_OF_BOUND,与略低于该边界值时已返回的错误一致。#112527 (groeneai)。 - 修复了
RENAME TABLE依据源数据库而非目标数据库检查表名最大长度的问题。将表重命名到名称较长的数据库中,可能产生DROP TABLE无法删除的表;而将表从此类数据库中重命名移出时,则会被错误地拒绝。#113019 (groeneai)。 - 修复了向
Alias表插入数据且其目标表会触发 materialized view 时,query_log中views列始终为空的问题。#113076 (eclbg)。 - 无效的
parallel_replicas_custom_key表达式 (例如tuple()或(x, y)) 现在会被拒绝并返回ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER,而不会再越界读取 custom-key 类型列表。#113359 (nickitat)。 - 修复了
RENAME DATABASE会接受过长的目标名称、导致该数据库中的表无法删除的问题。现在无论check_table_dependencies如何设置,都会执行表名长度检查,且检查范围也涵盖分离的表——此前这些表从未被检查,因此即使在默认设置下也会受到影响。#113557 (groeneai)。 - 向使用
Distributed引擎的表进行后台插入时,因向远程分片发送数据反复出错而产生的延迟,现在会在错误解决后逐步减少。此前该延迟只增不减,且永远不会重置。#87378 (Blackmorse)。 - 现在会拒绝针对未知集群或未配置
<secret>的集群使用USER_INTERSERVER_MARKER的原生协议握手。此前,此类握手会让未经身份验证的客户端进入服务器间模式,并执行由fake_interserver_context支撑的认证前协议数据包 (例如TablesStatusRequest) ,从而无需证明知晓集群 secret 即可获取本地表的信息。#99675 (MillaFleurs)。
SQL、analyzer 与 JOIN 相关修复
- 修复命名
WINDOW子句定义中的查询参数替换问题。此前,其中的参数未被替换,也不会报错;未设置的Identifier参数还可能在执行EXPLAIN SYNTAX时引发异常Logical error: '!part.empty()'。#110506 (alexey-milovidov)。 - 修复并发删除或替换可刷新materialized view 时偶发的服务器崩溃问题。在调度代码暂时释放互斥锁期间,如果另一个线程将任务的
view设置为nullptr,就会导致RefreshTask::doScheduling解引用空指针。#105588 (groeneai)。 - 修复使用
EXCEPT或INTERSECT定义、且操作数为UNION链的视图在执行DETACH/ATTACH或服务器重启后返回错误结果的问题。格式化程序未给INTERSECT/EXCEPT的UNION子节点添加括号,导致存储的 SQL 在重新解析时运算优先级颠倒。#105935 (groeneai)。 - 修复对使用
WITH CUBE、WITH ROLLUP或GROUPING SETS的GROUP BY结果按相同键执行SELECT DISTINCT时返回错误结果 (重复行) 的问题。在这些情况下,query_plan_remove_redundant_distinct优化不再移除DISTINCT,因为这些分组修饰符会生成键列取默认值的额外行,而这些默认值可能与实际分组的键值相同。#107072 (groeneai)。 - 修复 OUTER JOIN 中
WHERE过滤器为包含常量项的合取表达式时返回错误结果的问题 (例如p AND 1,或WHERE p QUALIFY NULL,其中QUALIFY NULL被合并到WHERE中) 。常量合取项可能被下推到连接的非保留侧,并从连接后的过滤器中移除,导致连接生成非保留侧列取默认值的未匹配行,而这些行错误地通过了过滤器。#107084 (groeneai)。 - 修复在
correlated_subqueries_default_join_kind = 'left'时,对将同一列标识符投影两次的数据源 (例如SELECT number, *) 执行关联标量子查询引发LOGICAL_ERROR(“无法在表达式操作 DAG 输入的对应位置找到输入列 …”) 并导致服务器异常终止的问题。#107112 (groeneai)。 - 修复使用旧版 analyzer (
enable_analyzer = 0) 时,JOIN使用空值安全比较运算符 (<=>/IS NOT DISTINCT FROM) 且其中一个连接键为标量子查询 (例如... JOIN t2 ON (SELECT x FROM t1) <=> t2.k) 所引发的LOGICAL_ERROR(在调试构建或启用 sanitizer 的构建中会导致服务器异常终止) 。此类查询现在返回常规的NOT_FOUND_COLUMN_IN_BLOCK错误,而非逻辑错误。#108123 (groeneai)。 - 修复将
join_algorithm = 'full_sorting_merge'用于SEMI/ANTI连接时引发的LOGICAL_ERROR(Join is supported only for pipelines with one output port) 和NOT_IMPLEMENTED(MergeJoinAlgorithm is not implemented for strictness Semi) 异常,也涵盖对EXISTS关联子查询去关联后生成的连接。full_sorting_merge现在会拒绝其无法执行的严格性/连接类型组合,使规划器回退到其他已启用的算法,或报告该连接无法执行。#108658 (groeneai)。 - 修复了一个 bug:
JOIN的WITH TOTALS行可能包含默认值 (例如0) ,而非来自连接一侧常量子查询的常量值。该错误结果仅在某些连接顺序下或启用query_plan_join_swap_table设置时出现。#108807 (vdimir)。 - 修复了 glibc 构建在信号栈尺寸较大的 CPU (例如搭载支持 AMX 内核的 Intel Sapphire Rapids / Granite Rapids) 上运行时启动中止的问题 (
Cannot allocate ThreadStack、EINVAL) 。原因是在调用aligned_alloc之前,信号备用栈大小未向上取整为页大小的整数倍。#108813 (groeneai)。 - 修复了关联子查询被去关联化为连接、且源关系中某个列名出现多次时引发的
Block structure mismatch in JoinStep逻辑错误 (在 debug/sanitizer 构建中会导致服务器中止) ,例如在correlated_subqueries_default_join_kind = 'right'下执行WITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM t。#109114 (groeneai)。 - 修复了
CREATE USER ... HOST LIKE 'a', 'b'(以及等效的ALTER USER) 静默地只保留第一个模式的问题。现在所有指定的HOST LIKE模式都会存储到该用户的主机允许列表中。#109187 (groeneai)。 - 修复了带常量
ON条件的ANY JOIN(例如t1 ANY INNER JOIN t2 ON 1) 返回意外结果的问题:该查询返回的是完整的笛卡尔积,而非 ANY 连接结果 #109207 (vdimir)。 - 修复了全局
max_rows_in_join/max_bytes_in_join限制对 parallel_hash 连接算法不生效的问题:此前设置了join_overflow_mode = 'throw'的查询可能静默成功,而不会抛出SET_SIZE_LIMIT_EXCEEDED。#109488 (m-selmi)。 - 修复了在服务器端内联插入解析路径 (
send_table_structure_on_insert_with_inline_data = 0) 下,多查询流中的INSERT ... VALUES后跟尾随 SQL 注释 (例如VALUES (1) -- comment) 时导致静默数据丢失的问题。此前该尾随注释会越过终止符;被当作行数据扫描,致使流中后续查询被静默跳过。#109643 (groeneai)。 - 修复了在
optimize_move_to_prewhere = 1下、PREWHERE于FINAL之后执行时延迟PREWHERE的问题:WHERE条件不再被移到延迟的行策略之前,此前这可能改变查询结果。#109703 (yariks5s)。 - 修复了递归 CTE 将外部作用域中的标识符解析为关联列时 (启用
allow_experimental_correlated_subqueries = 1) 出现的LOGICAL_ERROR(query tree node does not have valid source node) 。此类查询现在会返回明确的UNSUPPORTED_METHOD错误。#109863 (groeneai)。 - 修复了
ORDER BY ... WITH FILL在Int64/UInt64列上跳过极大间隙时 (例如以步长 2 跨越接近 2^63 的间隙) 出现的有符号整数溢出问题。该溢出在 sanitizer 下属于未定义行为,在发布构建中则会静默回绕。#109937 (groeneai)。 - 修复了在使用旧版 analyzer (
enable_analyzer = 0) 时,若INTERPOLATE目标是WITH FILL列的别名,会出现Invalid number of rows in Chunk逻辑错误的问题。此类查询现在会被拒绝,并返回明确的INVALID_WITH_FILL_EXPRESSION错误。#110103 (groeneai) 。 - 修复了包含关联子查询 (例如
exists((SELECT ...))) 的过滤条件在经convert_query_to_cnf或optimize_and_compare_chain优化时出现的逻辑错误 (Unexpected number of columns in result sample block) 。#110187 (alexey-milovidov) 。 - 嵌套的关联
EXISTS子查询如果引用了其直接外层查询之外的作用域中的列 (即跳过了中间作用域) ,现在会报出明确的NOT_IMPLEMENTED错误,而不再抛出内部错误NOT_FOUND_COLUMN_IN_BLOCK。#110310 (groeneai) 。 - 修复了当外层查询的关联列存在重复值、且子查询通过 CROSS JOIN 路径去关联时,关联标量子查询返回错误结果的问题。此前,
count()、sum()等聚合结果会被错误地乘以重复次数。此问题影响 experimental 功能allow_experimental_correlated_subqueries。#110311 (groeneai) 。 - 修复了
ORDER BY ... WITH FILL在生成较大填充范围时 (尤其是配合INTERPOLATE使用时) 不遵守max_execution_time、且难以及时取消的问题。#110332 (alexey-milovidov) 。 - 当查询按 sorting key 顺序读取时,不再应用延迟
FINAL优化 (query_plan_optimize_lazy_final,默认禁用) 。原因在于该优化替换后的执行计划不会按 sorting key 顺序输出行,而上层计划在经过按序读取优化后可能已依赖这一顺序,进而导致结果排序错误。此外,当小于待读取行数的LIMIT直接作用于读取步骤时,也不再应用该优化,因为其必需的集合构建过程会使提前终止机制失效。#110576 (KochetovNicolai) 。 - 后台异步插入的刷写操作在被
KILL QUERY终止时现在能够及时停止;此前,刷写大量缓冲数据时会无视取消请求,一直解析到结束。#110652 (tiandiwonder) 。 - 修复了位于
partial_mergeJOIN 之上的GROUP BY ... optimize_aggregation_in_order和DISTINCT ... optimize_distinct_in_order返回错误结果的问题。此前,按序读取优化会穿过PartialMergeJoin向下传播,但后者会按连接键对左侧输入重新排序,无法保留左侧数据流的原始顺序,从而导致行分组错误。#110671 (groeneai) 。 - 修复了在
INTERSECT或EXCEPT查询中使用 CTE 列别名时 (例如WITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t) ,查询因 UNKNOWN_IDENTIFIER 错误而失败的问题。#110885 (yariks5s) 。 - 修复了
grace_hash连接中,多个线程共享读取器且读取溢出块中途失败时可能出现的LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it.错误。#111056 (groeneai) 。 - 修复了在 *_hash JOIN 期间物化右侧列时使用错误时区的问题。#111074 (yariks5s)。
- 修复带有
COMMENT子句的CREATE语句在缺少注释字符串字面量时的行为:现在会抛出语法错误,而不再静默接受被错误解析的查询 (例如,CREATE VIEW v COMMENT AS SELECT 1不会再创建一个不带注释的视图) 。#111159 (tiandiwonder)。 - 修复复用的 materialized CTE (
enable_materialized_cte) 在WITH TOTALS或extremes输出被丢弃的分支上被读取时出现的LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) ,涉及外层聚合、INSERT ... SELECT、集合操作以及EXPLAIN ANALYZE等场景。#111194 (groeneai)。 - 修复
join_algorithm = 'full_sorting_merge'在LEFT/RIGHT/FULL/ASOFJOIN中使用原始零值而非列类型默认值填充未连接行的问题。对于Enum列 (其默认值为第一个元素,而非0) ,这会导致结果错误 (对填充值的过滤会丢弃未匹配的行,使外连接在无提示的情况下退化为内连接) ,并在查询该列时引发UNKNOWN_ELEMENT_OF_ENUM错误。#111197 (groeneai)。 - 修复在
optimize_move_to_prewhere_if_final = 1且WHERE子句为排序键列上的隐式布尔条件 (例如WHERE k) 时,SummingMergeTree(以及CoalescingMergeTree) 配合FINAL返回错误结果的问题。此前键列的值会跨未合并的分片被累加后返回,而不是保持原值。#111342 (groeneai)。 - 修复当左侧包含经
UNION ALL保留下来的重复同名列 (例如1 AS b, 1 AS b) 时,RIGHT/FULL JOIN可能出现的逻辑错误 (Unexpected number of columns in result sample block) 。#111554 (groeneai)。 - 修复格式化
EXECUTE AS查询时,若其 AST 中某个子节点已被替换 (AST fuzzer 就会这样做) ,客户端会崩溃的问题。ASTExecuteAsQuery现在拥有其target_user和subquery子节点的所有权,不再持有指向children的非拥有型指针。#111725 (groeneai)。 - 修复在
join_any_take_last_row = 1时query_plan_join_swap_table交换ANY JOIN两侧导致结果错误的问题:ClickHouse 现在会保留原有的连接侧顺序,确保ANY JOIN仍返回最后一个匹配行。#112458 (vdimir)。 - 修复在子查询中使用
getClientHTTPHeader时出现Context has expired异常的问题。#112533 (alexey-milovidov)。 - 修复
ON子句包含混合条件 (即跨两侧的非等值残余条件,例如ON (t1.key = t2.key) AND (t1.a * 10 < t2.a)) 的JOIN返回错误结果的问题。只有哈希系列算法能够计算此类条件,但full_sorting_merge、partial_merge以及直接键值连接此前声称支持执行这类连接,实际却静默忽略了残余条件,导致返回多余的行。现在它们会拒绝执行此类连接,转而使用哈希算法。#112831 (groeneai)。 - 修复了逗号连接或
CROSS连接的WHERE通过非确定性表达式 (如rand) 比较两个表的列时返回错误结果的问题。此类查询可能返回与其自身WHERE子句相矛盾的行,原因是将该连接改写为INNER连接时,该表达式被移入了连接键,而连接键会针对每一侧的每一行重新求值。#112938 (groeneai)。 - 修复了解析末尾带有大量无法识别字符的 PromQL 查询 (例如使用 NUL 字节填充的
FixedString值) 时出现的二次方级性能下降问题:由于解析发生在查询分析阶段,解析兆字节级的无效输入以往会使某个线程持续忙碌数十分钟,且无法取消。现在解析器遇到第一个错误时即会停止。#112944 (alexey-milovidov)。 - 修复了对非常量列使用常量除数 -1 调用
intDiv时,最小有符号数的除法 (例如intDiv(-9223372036854775808, -1)) 会静默溢出回绕,而不是像其他执行路径那样抛出ILLEGAL_DIVISION异常的问题。这种静默回绕还可能导致ORDER BY/DISTINCT结果错误:按顺序读取优化会正确地将除以负常量的intDiv视为单调函数,而回绕后的值破坏了由此得出的排序顺序。#113048 (alexey-milovidov)。 - 修复了在
enable_analyzer = 0时,若WHERE引用子查询中由untuple生成的列,会报UNKNOWN_IDENTIFIER错误的问题,例如SELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0。enable_optimize_predicate_expression改写会将此类谓词以HAVING的形式下推到子查询中,而此时该名称尚不存在。#113760 (groeneai)。 - 修复了在
join_algorithm = 'partial_merge'下,当右侧带有 totals 时JOIN返回错误结果的问题:右侧可能未被合并,导致LEFT连接用默认值替代了真实匹配,而INNER/RIGHT连接则完全不返回任何行。在RIGHT/FULL的未连接行处理路径中,同样的状态会导致空指针解引用,进而使服务器崩溃。#113936 (groeneai)。 - 修复了
SELECT DISTINCT搭配需要读取全部输入的LIMIT时返回错误结果的问题:LIMIT n WITH TIES会丢弃并列的行,exact_rows_before_limit = 1会报告被截断的rows_before_limit_at_least,而GROUP BY ... WITH TOTALS仅根据数据流的前一部分计算 totals 行。#114025 (groeneai)。 - 修复了
SELECT ... FINAL的PREWHERE使用了FINAL合并所需的列 (ver、is_deleted、sign) 但未选择该列时,抛出LOGICAL_ERROR(“Unexpected number of kept output positions after removing unused columns fromReadFromMergeTree”) 的问题。#114746 (groeneai)。 - 修复了异步 INSERT 刷新、物化视图处理以及
EXPLAIN ANALYZE中的生命周期问题,该问题可能导致访问已过期的查询跟踪状态。#114940 (azat)。 - 修复了在时间间隔之间省略分隔逗号时,
CREATE QUOTA和ALTER QUOTA会静默丢弃除最后一个FOR INTERVAL块之外所有块的问题。此类语句虽然执行成功,但之前的限制均未生效。现在这些时间间隔会像 2020 年之前那样重新累加生效。#115320 (groeneai)。 - 修复了
randConstant的多次调用带有不同别名时,在同一查询中返回两个不同值的问题。按照文档说明,randConstant在整个查询中应只有一个值,且SELECT randConstant() = randConstant()此前已能返回1,但如果像SELECT randConstant() AS a, randConstant() AS b这样添加别名,就会得到两个互不相关的值。#115384 (alexey-milovidov) 。 - 修复了对损坏的
MsgPack或ProtobufList文件执行SELECT count()时永不结束或返回虚构行数的问题。optimize_count_from_files快速路径在统计行数时不要求读取位置向前推进,因此一个仅有两字节的ProtobufList文件会产生数十亿行,且查询始终无法返回。现在此类输入会被拒绝,并报出与常规读取路径相同的错误。#115884 (groeneai) 。 - 修复了
system.distribution_queue中的broken_data_files以及BrokenDistributedFilesToInsert指标始终报告0的问题:启动时扫描异步插入队列的过程中,DistributedAsyncInsertDirectoryQueue::initializeFilesFromDisk统计了损坏的字节数,却始终没有递增损坏文件计数器。#92124 (squalfof) 。
其他缺陷修复
- 作为内部查询一部分执行的次级查询,现在会作为内部查询记录到日志中。#108506 (mstetsyuk)。
- 修复了当 PREWHERE 条件被拆分为多个读取步骤时,分片中缺失的 DEFAULT 列被填充为类型默认值、而非 DEFAULT 表达式计算结果的问题。#111795 (yariks5s)。
- 以
normalized_query_hash为键的配额现在会与查询计数器一样,按查询模式统计所有资源 (read_rows、read_bytes、result_rows、result_bytes、execution_time、written_bytes、errors) ,而不再全部计入每个用户共享的单个桶中。#107681 (alexey-milovidov)。 - 修复了 MySQL
connect_timeout以及读写超时不生效的问题:由于采样查询 profiler 的周期性信号会不断重置 MySQL 客户端内部的 poll 截止时间,即使设置了connect_timeout = 1,连接无响应的 MySQL 服务器时仍可能挂起两分钟以上。#109592 (tiandiwonder)。 - 修复了查询 profiler 启用时,流式插入的块等待超时 (
input_format_max_block_wait_ms) 可能永远不会触发的问题:每收到一次 profiler 信号,文件描述符的 poll 都会以完整的超时时间重新计时,导致输入源停滞时,部分块的刷写可能被无限期推迟,而不是在达到等待上限时执行。#109602 (tiandiwonder)。 - 修复了启用实验性设置
make_distributed_plan = 1的查询在distributed_plan_default_reader_bucket_count或distributed_plan_default_shuffle_join_bucket_count取值过大时出现LOGICAL_ERROR(std::length_error) 的问题。现在此类取值会被拒绝,并返回INVALID_SETTING_VALUE。#109770 (groeneai)。 - 修复
distinct_overflow_mode = 'break'的行为:DISTINCT 现在会按文档所述,返回达到上限前累积的部分结果,并停止读取数据源。此前,超出max_rows_in_distinct/max_bytes_in_distinct的那个块会被丢弃 (导致结果被截断或为空) ,且查询会继续读取数据并插入哈希集合,直至输入结束,最终可能引发MEMORY_LIMIT_EXCEEDED。#110075 (skuznetsov-clickhouse)。 - 修复
optimize_aggregation_in_order忽略查询取消的问题。AggregatingInOrderTransform现在会在聚合块的过程中检查取消状态,因此被KILL QUERY或max_execution_time(在默认的timeout_overflow_mode = 'throw'下) 终止的查询能够及时停止,而不必等整个块处理完毕。#110104 (groeneai)。 - 修复了从
mysql/postgresql/sqlite系列 PostgreSQL 数据源读取的值无法解析为所声明类型时 (例如将text列声明为Int32) ,服务器中止的问题 (仅限 debug 和 sanitizer 构建) 。此类类型不匹配现在会作为查询错误报告,不再导致服务器中止。#110264 (groeneai)。 - 修复了解析某些 PRQL 查询 (
SET dialect = 'prql') 时服务器中止的问题。此前prqlc编译器内部发生 panic 时会直接中止进程,而不是作为查询错误报告。#110316 (groeneai)。 - 修复当行策略和
additional_table_filters引用同一个未在查询中选取的列时出现NOT_FOUND_COLUMN_IN_BLOCK的问题。#111099 (groeneai)。 - 修复了
randChiSquared、randStudentT、randFisherF和randBinomial在使用极端参数时挂起的问题。此前此类查询无法通过max_execution_time或KILL QUERY中断。现在,即使将max_rand_distribution_parameter或max_rand_distribution_trials设置为 0,此类参数也会被拒绝;并且对于randBinomial,max_rand_distribution_trials不能再调高到超过其默认值 10^9。#111909 (alexey-milovidov)。 - 修复了
connection_pool_max_wait_ms的行为,使其文档所述的默认值0真正表示无限超时。此前,查询在发现连接池已满时会在紧密循环中反复重试,占用 CPU,并在每次迭代时记录No free connections in pool. Waiting 0 ms.。现在它会一直等待,直到有连接归还到连接池。#112380 (groeneai)。 - 修复了
replaceOne、replaceAll、replaceRegexpOne和replaceRegexpAll忽略max_execution_time和KILL QUERY的问题。现在单次调用在执行过程中会检查是否已被取消,因此针对大值或大量行的长时间替换操作会及时停止,而不会一直占用服务器线程直至完成。此类调用没有可返回的部分结果,因此在timeout_overflow_mode = 'break'下,它会将超时作为错误引发:常量折叠时总是如此;在管道中,只要该检查点先于 executor 的块间检查被触发,也会如此 (块间检查仍会静默停止查询) 。#112483 (groeneai)。 - 修复了
countSubstrings、countSubstringsCaseInsensitive和countSubstringsCaseInsensitiveUTF8忽略KILL QUERY和max_execution_time的问题:此前,处理大量行或大量匹配项的调用可能在查询取消后仍持续运行数分钟。#113369 (groeneai)。 - 修复了查询在发起服务器上极快完成时可能挂起 (长达
receive_timeout秒) 的问题。#113551 (nickitat)。 - 修复了
countMatches和countMatchesCaseInsensitive在统计单个大值的匹配数时忽略max_execution_time和KILL QUERY的问题,该问题会导致已取消的查询仍持续运行数分钟。当参数为常量时,调用发生在查询分析阶段,此时尚无管道可用于取消该调用。#113886 (groeneai)。 - 修复了查询可能在达到
max_execution_time前最多 1 ms 就被取消,并报出自相矛盾的错误Timeout exceeded: elapsed 999.672 ms, maximum: 1000 ms的问题。#114559 (alexey-milovidov)。 - 修复了
pointInPolygon在使用边界框无界的常量多边形 (例如某个坐标达到+-DBL_MAX) 时发生越界读取的问题。现在此类多边形会被拒绝并报错BAD_ARGUMENTS,而包含空环的多边形会被视为没有内部区域。此前,该查询可能返回错误结果,或在启用了加固或 sanitizer 的构建中导致服务器中止。#115035 (groeneai)。 - 修复了一个竞态条件,该问题可能导致
STREAM BOUNDED查询返回的行数少于其开始前已提交的行数 (通常一行都不返回) 。#115543 (alexey-milovidov)。 - 修复了在
make_distributed_plan = 1下,当窗口查询的排序列经过一个未引用该列的Expression步骤时,查询计划优化期间引发Unknown identifier错误的问题。#115890 (groeneai)。 - 修复了
h3kRing、h3HexRing、h3Line和h3ToChildren在展开行块时忽略max_execution_time和KILL QUERY的问题。#115893 (alexey-milovidov)。 - 修复了原生 Parquet V3 读取器中,当
PREWHERE的多个合取项共享同一个中间表达式时出现NOT_FOUND_COLUMN_IN_BLOCK错误的问题 (由先前的回归引入) 。#107059 (groeneai)。 - 修复了在启用
output_format_parquet_parallel_encoding(默认启用) 且max_threads大于 1 时写入 Parquet 会挂起的问题。如果编码器未能调度额外的线程,其活动线程计数器会发生下溢,导致写入可能永久停滞,既无法完成也不会报错。#112959 (groeneai)。 - 修复了读取 Parquet 文件时,若其 Thrift 元数据声明的容器或字符串长度大于元数据本身,会导致无限制内存分配的问题。现在此类长度会被直接拒绝,不再为其分配内存。#113212 (groeneai)。
- 修复了 Parquet v3 读取器中的
std::out_of_range异常 (Logical error: 'std::exception. Code: 1001, type: std::out_of_range',在 debug 和 sanitizer 构建中还会导致服务器中止) :当某个仅用于过滤求值的列在其输出槽位已被丢弃后才被调度解码时,就会触发该异常。#113956 (groeneai)。 - 修复了 profile events 和内存跟踪器中的数据竞争问题。#112466 (mstetsyuk)。
- 修复了使用
trace_profile_events_list设置将特定 profile events 的堆栈跟踪写入system.trace_log时,profile events 中理论上可能出现的数据竞争。#113553 (mstetsyuk)。 - 修复了当除法运算引发浮点异常 (除以零或
INT_MIN / -1) 时,intDivOrNull、moduloOrNull和positiveModuloOrNull返回0而非NULL,以及intDivOrNull和intDivOrZero抛出异常而非返回NULL/0的问题,有符号/无符号混合参数的情况也已一并修复。#101976 (yariks5s)。 - 修复了
Array和Map值与NULL比较时IS DISTINCT FROM结果不正确的问题。#103162 (ylw510)。 - 修复了
groupConcat混用参数化写法和双参数写法时的问题,例如groupConcat(',', 2)(x, '/'):此前行数限制参数会被静默丢弃,导致返回所有行而非指定的行数;现在第二个参数中的分隔符会正确覆盖该参数。#104882 (yariks5s)。 - 修复了使用 CAST 将较小的时间间隔单位转换为较大单位时存在的缺陷。#105058 (yariks5s)。
- 修复了在按序读取管道 (
optimize_read_in_order = 1且read_in_order_use_virtual_row_per_block = 1) 下运行LIMIT ... WITH TIES查询时出现的逻辑错误 (Assertion 'row < chunk.getNumRows()' failed) 。#105102 (groeneai)。 - 修复了在查询中同时使用
enable_sharding_aggregator = 1和UNION ALL,且max_streams_for_union_step小于管道宽度时出现的Logical error: 'Pipeline stuck'。现在,BufferedShardByHashTransform会在输入耗尽后立即结束空队列的输出端口;当某个被请求的空端口没有可排出的数据时,即使相邻队列已达到背压上限,它也会继续拉取输入。#106251 (groeneai)。 - 修复了在
plain对象存储磁盘 (例如s3_plain) 上,removeDirectory会像递归删除一样删除非空目录中所有文件的问题。现在删除非空目录会失败并报错CANNOT_RMDIR,而递归删除会显式处理目录内容。#106281 (RinChanNOWWW)。 - 修复了配置了
<lifetime>的executable_pool用户自定义函数无法感知底层脚本变更的问题。此前,只有SYSTEM RELOAD FUNCTIONS才会重新读取修改后的脚本;而按<lifetime>周期性重新加载时,执行的仍是旧版本。#107087 (groeneai)。 - 修复了工作线程启动 profiler 与服务器关闭之间,在服务器全局 trace collector 上发生的数据竞争。#107307 (groeneai)。
- 修复了服务器关闭期间偶发的异常中止问题 (
std::future_error,“The associated promise has been destructed prior to the associated state becoming ready”) ,其原因是通过threadPoolCallbackRunnerUnsafe调度的任务在运行前就被从线程池队列中丢弃。#107383 (groeneai)。 - 修复了
FileLog的逻辑错误 (Last stored last_written_position in meta file ... is bigger than current last_written_pos) ,该错误可能在被监视的文件被删除并以相同 inode 重新创建时出现。#107617 (groeneai)。 - 修复了
toTime64和CAST(... AS Time64)在saturate和ignore溢出模式下未将超出范围的值限制在Time64范围内的问题,该问题可能导致某些值显示相同、比较时却不相等。#108028 (alexey-milovidov)。 - 修复了正则表达式 “match all” 类函数
extractAll、extractAllGroupsVertical、extractAllGroupsHorizontal、countMatches和splitByRegexp对零宽断言 (\b、^、$) 处理不正确的问题。例如,extractAll('new york is the greatest', '\b(\w)')现在会正确返回每个单词的首字母,而不是所有字母。#108047 (alexey-milovidov)。 - 修复了在使用非
splitByNonAlpha分词器的文本索引上调用hasToken时返回错误结果的问题。#108066 (rschu1ze)。 - 修复了当输入精度高于时间间隔单位时,
toStartOfInterval和dateTrunc返回四舍五入后的值、而非所在时间间隔起点的问题。例如,toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond)返回的是10:11:12.001而非10:11:12.000。带显式 origin 参数的重载同样受影响。#108186 (yariks5s)。 - 修复了
replaceRegexpOne和replaceRegexpAll,使.默认匹配换行符,与其他正则表达式函数的行为保持一致。#108265 (linjiayu1025-collab)。 - 修复了轻量级 UPDATE/DELETE 的条件被重复计算两次的问题。#108323 (ofeliacode)。
- 修复了
arrayPartialSort()在 limit 参数为非常量时出现的问题。#108327 (vitlibar)。 - 修复了正则表达式函数 (
match、extract、extractAll、replaceRegexpOne、replaceRegexpAll等) 在模式中包含 NUL (\0) 字节时静默返回错误结果的问题。现在 NUL 会被视为普通的字面字节,与 RE2 的行为一致。#108427 (alexey-milovidov)。 - 修复了
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond作用于DateTime64(N)参数时,使用硬编码的默认标度 (3) 而非N来创建结果列的问题。此前值按标度N计算,但列对象声明的标度为 3,导致其结构与类型不一致。#108551 (groeneai)。 - 修复了当集合运算 (
INTERSECT/UNION ALL/EXCEPT) 所组合的分支中使用了关联子查询,且设置了correlated_subqueries_default_join_kind = 'left'时出现的LOGICAL_ERROR(“Trying to extract chunk from ChunkBuffer before all inputs are finished”) 。#108554 (groeneai)。 - 修复了
changeYear、changeMonth、changeDay、changeHour、changeMinute和changeSecond中与DateTime64相关的缺陷:纳秒精度 (标度 9) 的输入不再抛出DECIMAL_OVERFLOW,纪元之前的亚秒级输入现在也能返回正确的日历秒。#108681 (takumihara)。 - 避免在编译超大正则表达式 (例如包含数十万个通配符的
LIKE或match模式) 时产生过多的服务器日志输出和过长的错误消息;此类模式现在会直接失败,并报出明确的CANNOT_COMPILE_REGEXP错误。#108821 (Algunenano)。 - 修复了当源类型与目标类型的物理类型相同时,
reinterpret(x, 'Decimal128(scale)')(以及目标为Decimal32/Decimal64/Decimal256/DateTime64的情况) 生成的结果列内部标度为源标度、而非所请求目标标度的问题。此前值本身正确,但列对象的结构与其声明的类型不一致。#108878 (groeneai)。 - 修复了在连接失步或处于模糊测试时,将超出范围的协议数据包类型转换为字符串 (例如在 “Unexpected packet from server” / “Received … packet” 错误消息中) 所引发的未定义行为。#108885 (groeneai)。
- 修复
changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond作用于DateTime64(N)时,以硬编码的默认标度 3 (而非N) 构建结果列的问题;同时修复timeSlots作用于DateTime64时,其声明的返回类型忽略可选参数Size标度的问题。这两个问题都会导致生成列的实际标度与声明类型不一致:将结果传给arrayPushBack/arrayPushFront/arrayConcat时会引发LOGICAL_ERROR(writeSlice expects same column types) ,而当Size使用最大标度时,timeSlots会返回错误的时间戳。#108994 (groeneai)。 - 修复 ProfileEvents 增量非单调的问题 #109180 (azat)。
- 修复
SAMPLE比率的指数绝对值超出Int32范围时 (例如SAMPLE 1e-3000000000) 被静默当作SAMPLE 1处理的问题。#109197 (Algunenano)。 - 修复了
toUTCTimestamp/fromUTCTimestamp(及其别名to_utc_timestamp/from_utc_timestamp) 和toTime64在DateTime64路径上的两个缺陷。其一,接近Int64边界时会发生有符号整数溢出 (现改用Int128计算,并截断到可表示范围内) 。其二,对于接近时区偏移边界的负小数值会返回错误结果:拆分秒数时向零截断,导致timezoneOffset()检查的是下一秒,从而可能在 DST/偏移变化处取错一侧。#109738 (groeneai)。 - 修复了行策略过滤表达式使用
arrayJoin时出现的逻辑错误 (column->size() == num_rows) ;此类过滤器现在会被拒绝。#109753 (Algunenano)。 - 修复了
generateRandomStructure()在类型嵌套超过内部深度限制时,偶尔会生成两个数据类型拼接在一起的无效结构字符串 (例如Decimal32(7)IPv4) ,导致结果无法解析的问题。#109928 (groeneai)。 - 修复了
accurateCastOrDefault中查询设置的传递问题,以及Dynamic和Variant所编码的源NULL值未能保留的问题。#109946 (Avogar)。#114912 (alexey-milovidov)。 - 修复
max_bytes_in_distinct和max_bytes_in_set:字符串键存储在 arena 中,而该 arena 未被纳入限制检查,因此对字符串键执行 DISTINCT / IN 时,内存占用可能超出字节限制,超出量可达全部键数据的大小 (且随键长度无上限增长) 。现在这些限制会将 arena 计算在内,与文档描述一致;字符串键接近字节限制的查询现在可能会更早 (且正确地) 触发限制。#110120 (skuznetsov-clickhouse)。 - 修复了读取内部维度大小为零的 Npy 文件时的问题,使物化后的行与优化及未优化的
count()结果保持一致。#110146 (qiuyanjun888)。 - 修复
indexHint/ignore/isZeroOrNull函数接收到类型解析为Nothing的参数时 (例如在indexHint(assumeNotNull(materialize(NULL)))这类表达式中) 出现的逻辑错误 (在 debug/sanitizer 构建版本中会导致服务器中止) 。#110192 (groeneai)。 - 修复了
plain_rewritable磁盘上的某个已有路径被重写为不同大小的内容后,读取文件出错的问题:内存中的元数据仍保留过时的文件大小,可能导致读取失败并报错UNEXPECTED_END_OF_FILE。#110304 (thevar1able)。 - 现在会拒绝小于 1.0 的
vector_search_index_fetch_multiplier值,以免计算出的拉取数量被截断为零,导致 ANN 搜索返回空结果。#110452 (tamish560)。 - 修复了插入的值中含有数值类型转换表达式 (例如
initializeAggregation('sumState', 0::UInt64)) 时,偶发Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormat错误的问题。#110637 (groeneai)。 - 修复了
readWKT拒绝带前导空白字符的 WKT 字符串 (例如readWKT(' POINT(1 2)')) 的问题,而带类型的readWKTPoint/readWKTPolygon/… 读取器以及 WKT 语法均接受此类字符串。#110706 (groeneai)。 - 修复了消耗时间间隔长度为零的配额 (例如 CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000) 时服务器崩溃 (整数除以零) 的问题。现在创建配额时会拒绝非正的时间间隔时长。#110846 (PedroTadim)。
- 修复了 FIPS 构建中使用 Ed25519 SSH 密钥 (
CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519',或在users.xml中配置此类密钥) 时发生崩溃的问题。Ed25519 未获 FIPS 认可,此类密钥现在会被拒绝,并返回明确的LIBSSH_ERROR错误。#110891 (thevar1able)。 - 基于
QBit的转置距离函数 (cosineDistanceTransposed、L2DistanceTransposed、dotProductTransposed) 现在对截断为precision个位平面的值采用有界的低精度重建,不再将其重建为粗粒度单元的下边界 (被丢弃的位以零填充) 。零填充会使所有重建值都偏向零,且在低精度下会退化:对于 precision 为 1 的QBit(BFloat16),仅保留符号位,因此所有值都被重建为±0.0,每一行的距离都是同一个常量,不含任何排序信息。现在的重建方式取决于丢弃了哪些位:原始Int8编码被重建为其单元中心 (与...TransposedQuantized路径已采用的Lloyd-Max重建一致) ;precision 为 1 的浮点值变为标准的符号量化;保留完整指数、仅丢弃尾数位的浮点值被重建为其所在 binade 内的有界中点 (真正的零或±0.0仍保持为精确零,并单独划出非有限值单元,使±inf保持精确的无穷大;关于存在歧义的NaN单元,请参见下文说明) ;而在指数位仍被截断时,则保留有界下边界,因此较小的precision能以精度换取速度,而不会让数值膨胀若干个数量级。全精度结果保持不变。#110911 (alexey-milovidov)。 - 修复了原生 ORC 读取器对损坏的 ORC 文件进行 schema 推断时的越界读取问题:此类文件的类型树所声明的列数多于 stripe footer 中的列编码数。现在会以
CANNOT_EXTRACT_TABLE_STRUCTURE错误拒绝此类文件,而不会在 debug/sanitizer 构建中导致服务器中止。#110967 (groeneai)。 - 现在每个 SSH 密钥都会单独计入
max_authentication_methods_per_user限制,因此无论使用何种语法,该限制都能一致生效。此前,单个ssh_key方法中的多个密钥只算作一个。#111181 (TheMC47)。 - Iceberg REST 目录在凭证过期时,现在会报告底层错误,而不再静默报告
UNKNOWN_TABLE。#111379 (alesapin)。 - 修复了
readWKTPoint/readWKT在处理带维度标记的空点 (例如POINT M EMPTY) 时,返回未初始化坐标 (标量) 或上一行坐标 (向量化) 的问题。此类输入现在会被拒绝并报CANNOT_PARSE_TEXT错误,与POINT EMPTY的行为保持一致。#111517 (groeneai)。 - 创建
minmax统计信息时,现在会发出警告,而不再抛出异常。#111785 (hanfei1991)。 - 确保
randBinomial在退化概率0和1下,无论试验次数多少均可正常使用。#112021 (alexey-milovidov)。 - 修复了
system.s3_queue_settings中bucketing_mode、partitioning_mode、partition_regex和partition_component的值显示错误的问题。#112300 (bharatnc)。 - PromQL 查询中的错误现在会报告正确的位置。#112494 (fallintoplace)。
SYSTEM DISABLE FAILPOINT现在会拒绝不存在的 fail point 名称,并像SYSTEM ENABLE FAILPOINT一样抛出BAD_ARGUMENTS。此前,名称输错时仍会报告成功,而目标 fail point 依旧处于启用状态,且不会提示实际上并未禁用任何内容。#112680 (groeneai)。- 修复了读取
Nested元素子列 (其所在列曾被删除后重新添加) 时类型错误的问题。将此类子列与其父列一同查询时,子列位置上返回的是整个元素,而数据块声明的仍是元素类型,从而在 release 构建中产生任意值,在 debug 和 sanitizer 构建中触发逻辑错误。#112769 (groeneai)。 - 拒绝单位重复或未按从大到小顺序排列的 PromQL 时长。#112954 (fallintoplace)。
- 修复了
replaceRegexpOne/replaceRegexpAll中的未定义行为 (向memcpy传入空指针) :当替换字符串引用了未参与匹配的捕获组时会触发该问题,例如replaceRegexpAll('abc', '(a)|(b)', '\\2')。#113012 (alexey-milovidov)。 - 修复了在 ClickHouse 26.3 中使用
unicode_word分词器创建的文本索引无法在后续版本中加载的兼容性问题。#113061 (rschu1ze)。 - 拒绝 PromQL 字符串转义中无效的 Unicode 代理码点。#113203 (fallintoplace)。
- 拒绝 PromQL 字符串中无效的跨分隔符转义。#113587 (fallintoplace)。
- 修复了当第一个参数在窗口帧内为常量时,
theilsU在该窗口帧上返回任意值而非 0 的问题。#113691 (alexey-milovidov)。 - 修复了通过原生协议接收某些格式错误的
Replicated序列化列时报告的错误码:此类列现在会以INCORRECT_DATA被拒绝,而不再报告LOGICAL_ERROR(后者在 debug 和 sanitizer 构建中会导致服务器中止) 。#114186 (Avogar)。 - 修复了对较低精度的
Decimal64进行重新缩放时若Int64溢出,会生成错误 (且往往符号相反) 的Time64字面量和IN列表常量的问题。此类转换现在会报告DECIMAL_OVERFLOW,与DateTime64分支及显式CAST的行为一致。#114546 (groeneai)。 - PromQL 选择器现已支持带引号的指标名和标签名。#114551 (fallintoplace)。
- 修复了
ReplicatedMergeTree表在经由 attach 线程执行的启动尝试失败后,一直处于只读状态的问题。现在会正确调度重启重试,自动恢复机制及其会话检查得以恢复正常。#114802 (azat)。 timeSeriesRange和timeSeriesFromGrid会对 1970 年之前的时间戳误报DECIMAL_OVERFLOW,原因是起始/结束时间戳被当作无符号值读取。此外,对于DateTime/UInt32时间戳,步长会被静默截断为低 32 位。现在所有计算均使用Int64进行。#114815 (vitlibar)。- 修复了查询因
MEMORY_LIMIT_EXCEEDED失败后,异步插入中可能出现异常的问题;同时修复了async_insert_queue_flush_on_shutdown,确保队列中的插入在服务器关闭时能够被刷写。#114839 (azat)。 - 修复了当
sequenceMatch、sequenceCount或sequenceMatchEvents的模式中包含事件编号0(例如sequenceMatch('(?0)')) 时,抛出out_of_range异常并以内部错误Code: 1001呈现的问题。此类模式现在会以BAD_ARGUMENTS被拒绝。仅包含单个符号的时间条件 (例如sequenceMatch('(?1)(?t>+)(?2)')) 此前会被静默视为(?t>0),现在会以SYNTAX_ERROR被拒绝。#115056 (groeneai)。 - 修复了当坐标不是
Float64时,geoToH3的错误信息中参数位置和类型均有误的问题。在默认设置geotoh3_argument_order = 'lat_lon'下,错误信息会指向另一个参数,并打印该参数的类型。#115503 (groeneai)。 - 修复了 text、tokenbf_v1 和 ngrambf_v1 索引中反斜杠转义字符无效的问题。#115634 (ahmadov)。
- 修复了
TZ环境变量为空时服务器无法启动的问题。#68921 (ardenwick)。