ClickHouse 24.9 版本发布说明

图片

本文字数:7295;估计阅读时间:19 分钟

作者:ClickHouse Team

本文在公众号【ClickHouseInc】首发

图片

又到新版本发布的时间了!

发布概要

本次ClickHouse 24.9 版本包含了23个新功能🎁、14性能优化🛷、76个bug修复🐛

本次更新亮点包括:可刷新物化视图新增 APPEND 子句、JSON 数据类型支持更多新函数、自动模式推断现在还支持返回 Variant 类型。

欢迎新贡献者

一如既往地欢迎 24.9 版本中的新贡献者!ClickHouse 的受欢迎离不开社区的持续努力,看到这个社区不断壮大,总是让人倍感欣慰。

以下是新加入的贡献者名单:

1on, Alexey Olshanskiy, Alexis Arnaud, Austin Bruch, Denis Hananein, Dergousov, Gabriel Mendes, Konstantin Smirnov, Kruglov Kirill, Marco Vilas Boas, Matt Woenker, Maxim Dergousov, Michal Tabaszewski, NikBarykin, Oleksandr, Pedro Ferreira, Rodrigo Garcia, Samuel Warfield, Sergey (Finn) Gnezdilov, Tuan Pham Anh, Zhigao Hong, baolin.hbl, gao chuan, haozelong, imddba, kruglov, leonkozlowski, m4xxx1m, marco-vb, megao, mmav, neoman36, okunev, siyuan

可刷新物化视图新增 APPEND 功能

贡献者:Michael Kolupaev

可刷新物化视图是一种实验性功能,能够将查询结果存储以便快速读取。在本次发布中,我们新增了 APPEND 功能,使得在更新视图时无需替换整个视图内容,而是直接将新行追加到表末尾。

这个功能的一个典型应用场景是捕获某一时间点的数据快照。假设我们有一个事件表,该表由 Redpanda、Kafka 或其他流数据平台的消息流持续填充。

SELECT *
FROM events
LIMIT 10

Query id: 7662bc39-aaf9-42bd-b6c7-bc94f2881036

┌──────────────────ts─┬─uuid─┬─count─┐
│ 2008-08-06 17:07:19 │ 0eb  │   547 │
│ 2008-08-06 17:07:19 │ 60b  │   148 │
│ 2008-08-06 17:07:19 │ 106  │   750 │
│ 2008-08-06 17:07:19 │ 398  │   875 │
│ 2008-08-06 17:07:19 │ ca0  │   318 │
│ 2008-08-06 17:07:19 │ 6ba  │   105 │
│ 2008-08-06 17:07:19 │ df9  │   422 │
│ 2008-08-06 17:07:19 │ a71  │   991 │
│ 2008-08-06 17:07:19 │ 3a2  │   495 │
│ 2008-08-06 17:07:19 │ 598  │   238 │
└─────────────────────┴──────┴───────┘

在这个数据集中,uuid 列包含 4096 个值。我们可以通过以下查询来找到总计数最高的那些值:

SELECT
    uuid,
    sum(count) AS count
FROM events
GROUP BY ALL
ORDER BY count DESC
LIMIT 10

┌─uuid─┬───count─┐
│ c6f  │ 5676468 │
│ 951  │ 5669731 │
│ 6a6  │ 5664552 │
│ b06  │ 5662036 │
│ 0ca  │ 5658580 │
│ 2cd  │ 5657182 │
│ 32a  │ 5656475 │
│ ffe  │ 5653952 │
│ f33  │ 5653783 │
│ c5b  │ 5649936 │
└──────┴─────────┘

例如,如果我们希望每 10 秒记录一次每个 uuid 的计数,并将这些计数存储在一个新表 events_snapshot 中,events_snapshot 的表结构可以是这样的:

CREATE TABLE events_snapshot (
    ts DateTime32,
    uuid String,
    count UInt64
) 
ENGINE = MergeTree 
ORDER BY uuid;

接下来,我们可以创建一个可刷新物化视图,将数据填充到这个表中:

SET allow_experimental_refreshable_materialized_view=1;

CREATE MATERIALIZED VIEW events_snapshot_mv
REFRESH EVERY 10 SECOND APPEND TO events_snapshot
AS SELECT
    now() AS ts,
    uuid,
    sum(count) AS count
FROM events
GROUP BY ALL;

然后,我们可以查询 events_snapshot 表,以获取某个特定 uuid 随时间变化的计数记录:

SELECT *
FROM events_snapshot
WHERE uuid = 'fff'
ORDER BY ts ASC
FORMAT PrettyCompactMonoBlock

┌──────────────────ts─┬─uuid─┬───count─┐
│ 2024-10-01 16:12:56 │ fff  │ 5424711 │
│ 2024-10-01 16:13:00 │ fff  │ 5424711 │
│ 2024-10-01 16:13:10 │ fff  │ 5424711 │
│ 2024-10-01 16:13:20 │ fff  │ 5424711 │
│ 2024-10-01 16:13:30 │ fff  │ 5674669 │
│ 2024-10-01 16:13:40 │ fff  │ 5947912 │
│ 2024-10-01 16:13:50 │ fff  │ 6203361 │
│ 2024-10-01 16:14:00 │ fff  │ 6501695 │
└─────────────────────┴──────┴─────────┘

Variant 类型的模式推断

贡献者:Shaun Struwig

ClickHouse 现在支持在模式推断中自动使用 Variant 数据类型。这一功能默认关闭,可以通过设置 ``input_format_try_infer_variants`` 来启用。

让我们来看一个示例,了解该功能如何运作。假设我们读取以下文件:

data1.json

{"id": [1], "name": "Mark"}
{"id": "agerty", "name": "Dale"}

文件中,id 字段在第一行是一个整数数组,在第二行是一个字符串。我们可以查询该文件以查看 id 列的类型:

select *, toTypeName(id)
FROM file('data1.json')
SETTINGS input_format_try_infer_variants=1;

┌─id─────┬─name─┬─toTypeName(id)──────────────────────────┐
│ [1]    │ Mark │ Variant(Array(Nullable(Int64)), String) │
│ agerty │ Dale │ Variant(Array(Nullable(Int64)), String) │
└────────┴──────┴─────────────────────────────────────────┘

如果没有启用 input_format_try_infer_variants=1,则会收到以下错误消息:

Received exception:
Code: 636. DB::Exception: The table structure cannot be extracted from a JSON format file. Error:
Code: 53. DB::Exception: Automatically defined type String for column 'id' in row 1 differs from type defined by previous rows: Array(Int64). You can specify the type for this column using setting schema_inference_hints. (TYPE_MISMATCH) (version 24.9.1.3278 (official build)).
You can specify the structure manually: (in file/path/to/24.9/data1.json). (CANNOT_EXTRACT_TABLE_STRUCTURE)

需要注意的是,Variant 类型并不总是会在您预期的地方被推断。例如,如果 id 字段中的值可以被转换为 String 类型,即使 Variant 类型也是可推断的,推断结果仍然会是 String 类型。以下文件就是这种情况:

data2.json

{"id": 1, "name": "Mark"}
{"id": "agerty", "name": "Dale"}
{"id": "2021-01-04", "name": "Tom"}

当运行以下查询时:

select *, toTypeName(id)
FROM file('data2.json')
SETTINGS input_format_try_infer_variants=1;

┌─id─────────┬─name─┬─toTypeName(id)───┐
│ 1          │ Mark │ Nullable(String) │
│ agerty     │ Dale │ Nullable(String) │
│ 2021-01-04 │ Tom  │ Nullable(String) │
└────────────┴──────┴──────────────────┘

id 列会被推断为 Nullable(String),因为所有值都可以被转换为字符串。不过,您仍然可以通过提供提示,将 id 列推断为 Variant 类型:

SET allow_experimental_variant_type=1;

SELECT *, toTypeName(id) 
FROM  file('data2.json') 
SETTINGS schema_inference_hints='id Variant(String, Int64, Date)';

┌─id─────────┬─name─┬─toTypeName(id)───────────────┐
│ 1          │ Mark │ Variant(Date, Int64, String) │
│ agerty     │ Dale │ Variant(Date, Int64, String) │
│ 2021-01-04 │ Tom  │ Variant(Date, Int64, String) │
└────────────┴──────┴──────────────────────────────┘

用于 JSON 数据分析的聚合函数

贡献者:Pavel Kruglov

在 24.8 版本中,我们介绍了新的 JSON 数据类型。这次更新中,我们为 JSON 和 Dynamic 数据类型新增了更多实用函数。以下是一个示例数据集:

data3.json

{"id": 1, "name": "Mark"}
{"id": "agerty", "name": "Dale"}
{"id": "2021-01-04", "name": "Tom"}
{"id": ["1", 2, "3"], "name": "Alexey", "location": "Netherlands"}

首先,distinctJSONPaths 函数可以用来返回唯一的 JSON 路径。

SELECT distinctJSONPaths(json)
FROM file('data3.json', JSONAsObject)
FORMAT Vertical;

Row 1:
──────
distinctJSONPaths(json): ['id','location','location.city','location.country','name']

如果您还想查看类型,可以使用 distinctJSONPathsAndTypes 函数:

SELECT distinctJSONPathsAndTypes(json)
FROM file('data3.json', JSONAsObject)
FORMAT Vertical;

Row 1:
──────
distinctJSONPathsAndTypes(json): {'id':['Array(Nullable(String))','Int64','String'],'location':['String'],'location.city':['String'],'location.country':['String'],'name':['String']}

最后,distinctDynamicTypes 函数可以返回 Dynamic 列中的唯一数据类型。

SELECT distinctDynamicTypes(json.id)
FROM file('data3.json', JSONAsObject)
FORMAT Vertical

Row 1:
──────
distinctDynamicTypes(json.id): ['Array(Nullable(String))','Int64','String']

URL 引擎支持 _headers 列

贡献者:Flynn

现在,查询 url 表函数时,可以通过 _headers 虚拟列访问响应头信息:

SELECT _headers
FROM url(
'https://en.wikipedia.org/w/api.php?action=query&list=recentchanges&rcprop=title%7Cids%7Csizes%7Cflags%7Cuser%7Cuserid%7Ctimestamp&format=json&rcdir=newer'
)
LIMIT 1
FORMAT Vertical;


Row 1:
──────
_headers: {'accept-ranges':'bytes','age':'0','cache-control':'private, must-revalidate, max-age=0','content-disposition':'inline; filename=api-result.json','content-type':'application/json; charset=utf-8','date':'Tue, 01 Oct 2024 15:32:59 GMT','nel':'{ "report_to": "wm_nel", "max_age": 604800, "failure_fraction": 0.05, "success_fraction": 0.0}','report-to':'{ "group": "wm_nel", "max_age": 604800, "endpoints": [{ "url": "https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0" }] }','server':'mw-api-ext.codfw.main-54d5bc66d9-98km5','server-timing':'cache;desc="pass", host;desc="cp3067"','set-cookie':'WMF-Last-Access=01-Oct-2024;Path=/;HttpOnly;secure;Expires=Sat, 02 Nov 2024 12:00:00 GMT','strict-transport-security':'max-age=106384710; includeSubDomains; preload','transfer-encoding':'chunked','vary':'Accept-Encoding,Treat-as-Untrusted,X-Forwarded-Proto,Cookie,Authorization','x-cache':'cp3067 miss, cp3067 pass','x-cache-status':'pass','x-client-ip':'82.35.72.115','x-content-type-options':'nosniff','x-frame-options':'DENY'}

overlay 函数

如果您需要将字符串片段替换为另一个字符串,overlay 函数让这一过程更为简单。只需提供初始字符串、替换字符串、替换的起始位置以及替换字符的数量即可。

我们可以利用这个函数来表达 chDB 【https://clickhouse.com/docs/en/chdb】的酷炫之处!

SELECT overlay('ClickHouse is cool', 'and chDB are', 12, 2) AS res

┌─res──────────────────────────┐
│ ClickHouse and chDB are cool │
└──────────────────────────────┘

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值