ClickHouse 24.11 版本发布说明
本文字数:5883;估计阅读时间:15 分钟
新的一月,又迎来了新版本的发布!
发布概要
本次ClickHouse 24.11 版本包含了9个新功能🎁、15项性能优化🛷、68个bug修复🐛
在本次更新中,并行哈希 Join 成为默认的 Join 策略,WITH FILL 支持 STALENESS 修饰符,可以预热标记缓存。同时,引入 BFloat16 数据类型,显著提升了向量搜索的速度。
正如往常,我们热烈欢迎 24.11 版本中的所有新贡献者!ClickHouse 的持续流行,很大程度上依赖社区的积极贡献。看到社区的不断壮大,令我们倍感荣幸。
以下是本次版本的新贡献者名单:
0xMihalich, Max Vostrikov, Payam Qorbanpour, Plasmaion, Roman Antonov, Romeo58rus, Zoe Steinkamp, kellytoole, ortyomka, qhsong, udiz, yun, Örjan Fors, Андрей
贡献者:Nikita Taranov
在本次版本中,并行哈希 Join 算法取代了哈希 Join,成为默认的 Join 策略。
并行哈希 Join 是哈希 Join 的一种改进算法,通过将输入数据分片并并发地构建多个哈希表,实现了更快的 Join 操作,但需要更多内存资源。以下是该算法的查询管道示意图:
关于并行哈希 Join 的更多技术细节,请参阅博客文章《ClickHouse Joins Under the Hood - Hash Join, Parallel Hash Join, Grace Hash Join》【https://clickhouse.com/blog/clickhouse-fully-supports-joins-hash-joins-part2】。
除了默认启用外,本次更新还对该算法进行了性能优化。现在,线程间分发的块在并行处理时使用零拷贝技术,避免了每次复制块列所带来的额外开销。
贡献者:Mikhail Artemenko
本次版本为 WITH FILL 引入了 STALENESS 修饰符。以下是结合 MidJourney 数据集的使用示例。假设我们已经下载了 Parquet 文件,可以通过以下查询将数据填充到表中:
CREATE TABLE images (id String,timestamp DateTime64,height Int64,width Int64,size Int64)ENGINE = MergeTreeORDER BY (size, height, width);INSERT INTO images WITH data AS (SELECTassumeNotNull(timestamp) AS ts,assumeNotNull(id) AS id,assumeNotNull(height) AS height,assumeNotNull(width) AS width,assumeNotNull(size) AS size,parseDateTime64BestEffort(ts) AS ts2FROM file('data/0000{00..55}.parquet'))SELECT id, ts2 AS timestamp, height, width, sizeFROM data;
如果我们想统计 2023 年 3 月 24 日某一秒内生成的图像数量,可以通过参数定义起始和结束时间:
SET param_start = '2023-03-24 00:24:02',param_end = '2023-03-24 00:24:03';
接着,我们可以使用 WITH FILL 子句计算每 100 毫秒的计数,同时为空桶填充值 0:
SELECTtoStartOfInterval(timestamp, toIntervalMillisecond(100)) AS bucket,count() AS count, 'original' as originalFROM MidJourney.imagesWHERE (timestamp >= {start: String}) AND (timestamp <= {end: String})GROUP BY ALLORDER BY bucket ASCWITH FILLFROM toDateTime64({start:String}, 3)TO toDateTime64({end:String}, 3) STEP toIntervalMillisecond(100);
┌──────────────────bucket─┬─count─┬─original─┐│ 2023-03-24 00:24:02.000 │ 0 │ ││ 2023-03-24 00:24:02.100 │ 0 │ ││ 2023-03-24 00:24:02.200 │ 0 │ ││ 2023-03-24 00:24:02.300 │ 3 │ original ││ 2023-03-24 00:24:02.400 │ 0 │ ││ 2023-03-24 00:24:02.500 │ 0 │ ││ 2023-03-24 00:24:02.600 │ 1 │ original ││ 2023-03-24 00:24:02.700 │ 1 │ original ││ 2023-03-24 00:24:02.800 │ 2 │ original ││ 2023-03-24 00:24:02.900 │ 0 │ │└─────────────────────────┴───────┴──────────┘
本次更新新增的 STALENESS 子句,其功能定义如下(摘自文档):
当定义了 STALENESS const_numeric_expr 时,查询将生成连续的行,直到前一行与当前行的时间差超过 const_numeric_expr。
在查询中,STALENESS 和 WITH FILL...FROM 子句不能同时使用,因此我们需要移除 WITH FILL...FROM。移除后,查询将如下所示:
SELECTtoStartOfInterval(timestamp, toIntervalMillisecond(100)) AS bucket,count() AS count, 'original' as originalFROM MidJourney.imagesWHERE (timestamp >= {start: String}) AND (timestamp <= {end: String})GROUP BY ALLORDER BY bucket ASCWITH FILLTO toDateTime64({end:String}, 3) STEP toIntervalMillisecond(100);
删除 WITH FILL...FROM 子句意味着结果集将从第一个实际存在的值开始,而不是从指定的时间戳回填 0 值。
┌──────────────────bucket─┬─count─┬─original─┐│ 2023-03-24 00:24:02.300 │ 3 │ original ││ 2023-03-24 00:24:02.400 │ 0 │ ││ 2023-03-24 00:24:02.500 │ 0 │ ││ 2023-03-24 00:24:02.600 │ 1 │ original ││ 2023-03-24 00:24:02.700 │ 1 │ original ││ 2023-03-24 00:24:02.800 │ 2 │ original ││ 2023-03-24 00:24:02.900 │ 0 │ │└─────────────────────────┴───────┴──────────┘
如果为 STALENESS 设置 200 毫秒的值,查询将仅填充空行,直到前一行与当前行的时间差超过 200 毫秒:
SELECTtoStartOfInterval(timestamp, toIntervalMillisecond(100)) AS bucket,count() AS count, 'original' as originalFROM MidJourney.imagesWHERE (timestamp >= {start: String}) AND (timestamp <= {end: String})GROUP BY ALLORDER BY bucket ASCWITH FILLTO toDateTime64({end:String}, 3) STEP toIntervalMillisecond(100)STALENESS toIntervalMillisecond(200);
┌──────────────────bucket─┬─count─┬─original─┐│ 2023-03-24 00:24:02.300 │ 3 │ original ││ 2023-03-24 00:24:02.400 │ 0 │ ││ 2023-03-24 00:24:02.600 │ 1 │ original ││ 2023-03-24 00:24:02.700 │ 1 │ original ││ 2023-03-24 00:24:02.800 │ 2 │ original ││ 2023-03-24 00:24:02.900 │ 0 │ │└─────────────────────────┴───────┴──────────┘
此时,以下行将从结果集中被移除:
│ 2023-03-24 00:24:02.500 │ 0 │ │贡献者:Sema Checherinda
从现在起,HTTP 接口可以在结果流式传输给客户端之后,仍然可靠地检测到错误。在之前的版本中,如果我们在 ClickHouse Server 上运行以下查询:
curl http://localhost:8123/?output_format_parallel_formatting=0 -d "SELECT throwIf(number > 100000) FROM system.numbers FORMAT Values"我们会先看到值流输出,随后附加如下的错误消息:
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 100000) :: 2) -> throwIf(greater(number, 100000)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 24.3.1.465 (official build))退出代码为 0,这表明查询被认为成功运行。而从 24.11 版本开始,我们将会看到如下输出:
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(__table1.number, 100000_UInt32) :: 0) -> throwIf(greater(__table1.number, 100000_UInt32)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 24.11.1.2557 (official build))curl: (18) transfer closed with outstanding read data remaining
并且返回了非零退出代码 18。
贡献者:Anton Popov
Mark 文件将主键映射到每列文件的偏移量,是表索引的一部分。每个表的列都对应一个 mark 文件。这些文件可能占用大量内存,并会按需加载到 mark 缓存中。
从 24.11 版本开始,你可以通过 mark_cache_prewarm_ratio 参数预热 mark 缓存,该参数默认值为 95%。
服务器会在每次插入、合并或提取数据部分时主动将 mark 文件加载到内存缓存中,直到缓存几乎填满。
此外,新增了一个系统命令 SYSTEM PREWARM MARK CACHE t,可以立即将所有 mark 文件加载到缓存中。
贡献者:Alexey Milovidov
BFloat16 数据类型由 Google Brain 团队开发,专用于表示向量嵌入。顾名思义,它由 16 位组成,其中 1 位为符号位,8 位为指数,7 位为尾数(小数部分)。
这一数据类型的指数范围与 Float32(单精度浮点数)相同,但尾数位数较少(7 位,而非 23 位)。
现在,ClickHouse 已支持 BFloat16 数据类型,非常适合用于 AI 和向量搜索场景。要使用这一新类型,需要进行以下参数配置:
SET allow_experimental_bfloat16_type=1;我们在 AWS c7a.metal-48xl 实例上进行了一项性能测试,对 28 百万个 384 维向量进行完整扫描的最近邻搜索,结果如下:
clickhouse-benchmark --query "WITH[-0.02925783360957671,-0.03488947771094666,...,0.032484047621093616]::Array(BFloat16)AS center SELECT d FROM (SELECT cosineDistance(vector, center) AS dFROM hackernews_llama_memory ORDER BY d LIMIT 10) SETTINGS allow_experimental_bfloat16_type = 1"
BFloat16: 0.061 sec, 301 GB/sec.Float32: 0.146 sec, 276 GB/sec.
注册ClickHouse中国社区大使,领取认证考试券
试用阿里云 ClickHouse企业版
轻松节省30%云资源成本?阿里云数据库ClickHouse 云原生架构全新升级,首次购买ClickHouse企业版计算和存储资源组合,首月消费不超过99.58元(包含最大16CCU+450G OSS用量)了解详情:https://t.aliyun.com/Kz5Z0q9G
征稿启示
面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:[email protected]