博客 / 产品

ClickHouse 21.12 版本新特性

author avatar
Alexey Milovidov 和 Christoph Wurm
2021 年 12 月 16 日 - 分钟阅读

我们正在继续我们的每月发布节奏。 21.12 Christmas 版本包含来自 125 位贡献者的 2460 个新提交,其中包括 42 位新贡献者

Alex Cao, Amr Alaa, Andrey Torsunov, Constantine Peresypkin, Dmitriy Dorofeev, Egor O’Sten, Elykov Alexandr, Evgeny, Frank Chen, LB, Natasha Murashkina, Peignon Melvyn, Rich Raposa, Roman Chyrva, Roman, SuperDJY, Thom O’Connor, Timur Magomedov, Tom Risse, Tomáš Hromada, cfcz48, cgp, cms, cmsxbc, congbaoyangrou, dongyifeng, frank chen, freedomDR, jus1096, khamadiev, laurieliyang, leosunli, liyang830, loneylee, michael1589, msaf1980, p0ny, qieqieplus, spume, sunlisheng, yandd, zhanghuajie。

如果您想知道,此列表是通过以下命令生成的

clickhouse-local --query "
    SELECT arrayStringConcat(groupArray(s), ', ')
    FROM file('contributors-21.12.txt', LineAsString, 's String')
    WHERE s NOT IN (
        SELECT *
        FROM file('contributors-21.11.txt', LineAsString, 's String'))
    FORMAT TSVRaw"

要列出贡献者,您可以随时在您的生产服务器上运行以下

SELECT * FROM system.contributors

查询。

让我们重点介绍 21.12 中的一些新功能

ClickHouse Keeper 功能已完善

在 21.12 版本中,clickhouse-keeper 开始支持 “四字命令”,用于状态和监控。此功能由 JackyWoo 贡献,并由 Alexander Sapin(ClickHouse Keeper 的作者)审核。

这是唯一缺少实现的功能。在此版本中,clickhouse-keeper 仍然被认为是预生产阶段,但许多公司已经开始评估并将其用作 ZooKeeper 的替代品。您也可以开始在测试环境中使用 clickhouse-keeper,我们将感谢您的反馈。

ClickHouse Keeper 的开发始于 2020 年 9 月,距今已有一年多的时间。这是一条漫长的道路,大部分努力都是为了确保在异常和特殊情况下的正确性和稳定性。它通过 Jepsen 测试(包括 ZooKeeper 测试和 新引入的测试)、使用 ClickHouse 功能和集成测试的持续随机压力测试进行覆盖。它已开始在 Yandex Cloud 和我们的挚友中进行测试。如果您想成为我们的挚友,您也可以这样做。

这对您有何帮助?

ClickHouse Keeper 是 ZooKeeper 的直接替代品。它实现了 ZooKeeper 的有线协议和数据模型,但做得更好。

与 ZooKeeper 相比,它没有 zxid 溢出或数据包大小的问题。它具有更好的内存使用率,并且不需要 JVM 调优(因为它不使用 JVM)。日志和快照被压缩(通常约为 10 倍)并进行校验和。它可以作为单独的进程运行,也可以直接在 clickhouse-server 内部运行。您可以将其与 ClickHouse 或您的 Kafka 和 Hadoop 一起使用。

更多信息.

用于 INSERT INTO File、URL 和 HDFS 存储的分区

当使用表引擎 FileURLHDFS 时,ClickHouse 现在支持分区。创建表时,您可以使用 PARTITION BY 子句指定分区键,例如 CREATE TABLE hits_files (...) ENGINE = File(TabSeparated) PARTITION BY toYYYYMM(EventDate)

类似地,当使用 fileurlhdfs 表函数从 ClickHouse 导出数据时,您现在可以指定使用 PARTITION BY 子句将数据分区到多个文件中。例如,INSERT INTO TABLE FUNCTION file('path/hits_{_partition_id}', 'TSV', 'columns...') PARTITION BY toYYYYMM(EventDate) VALUES ... 将创建与数据集中唯一月份数量相同的文件。

s3 表函数自 ClickHouse 21.10 以来已支持分区写入。

这对您有何帮助?

如果数据被拆分为多个文件,SELECT 查询将自动并行化。例如

SELECT user_id, count() FROM s3(
    'https://s3.us-east-2.amazonaws.com/.../*.csv.zstd',
    '...', '...',
    CSV,
    'user_id UInt64, ...')

如果您使用 s3Cluster 表函数,您甚至可以在分布式计算集群中并行化数据处理

SELECT user_id, count() FROM s3Cluster(
    my_cluster,
    'https://s3.us-east-2.amazonaws.com/.../*.csv.zstd',
    '...',
    '...', CSV,
    'user_id UInt64, ...')

它也可以用于与使用 s3 中的数据的外部数据处理工具集成。

clickhouse-client 中的 FROM INFILE 现在支持 glob 模式和并行读取

只需编写

INSERT INTO my_table FROM INFILE '*.csv.gz' FORMAT CSV

Glob 模式支持 *?{n..m},形式为 {1..10} 或(对齐的){01..10}

此查询将自动并行化,并且还将自动从文件扩展名检测压缩格式并透明地解压缩。

此改进由 Arthur Filatenkov 完成。

这对您有何帮助?

现在您不必回忆起如何在命令行 shell 中编写并行 for 循环。 clickhouse-client 将为您完成一切,它工作直观且快速。

在 ORDER BY 子句的 WITH FILL 修饰符中支持 INTERVAL 运算符

ORDER BY 子句中的 WITH FILL 修饰符是什么?看看这个例子

:) SELECT EventDate, count() FROM test.hits WHERE CounterID = 2841673 GROUP BY EventDate ORDER BY EventDate

┌──EventDate─┬─count()─┐
│ 2014-03-173 │
│ 2014-03-196 │
│ 2014-03-217 │
│ 2014-03-226 │
└────────────┴─────────┘

我们有 3 月 17 日、19 日、21 日和 22 日的报告。但 3 月 18 日和 20 日缺失了,因为这些日期没有数据。

这在所有 SQL 数据库中都是如此。

但 ClickHouse 还为 ORDER BY 子句提供了一个非常独特且简洁的 WITH FILL 修饰符。

您只需编写

SELECT EventDate, count() FROM test.hits WHERE CounterID = 2841673 GROUP BY EventDate
ORDER BY EventDate WITH FILL STEP 1

┌──EventDate─┬─count()─┐
│ 2014-03-173 │
│ 2014-03-180 │
│ 2014-03-196 │
│ 2014-03-200 │
│ 2014-03-217 │
│ 2014-03-226 │
└────────────┴─────────┘

缺失的数据将自动填充。

您还可以添加 FROMTO

ORDER BY EventDate WITH FILL FROM '2014-03-01'::Date TO '2014-03-31'::Date STEP 1;

它将自动填充报告中缺失的行。

STEP 可以是任意数字。但是,如果您想按月填充报告中缺失的日期,该怎么办?您不能只写 STEP 30STEP 31,因为不同的月份包含不同的天数...

自 ClickHouse 21.12 版本起,您可以这样做

ORDER BY EventDate WITH FILL STEP INTERVAL 1 MONTH

INTERVAL 是一个标准的 SQL 运算符,您可以使用 SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER 和 YEAR。

这是由 “WITH FILL” 功能的作者 Anton Popov 实现的。

这对您有何帮助?

它允许您避免报告的后处理步骤。

为 “Identifier” 表和数据库查询参数添加支持

ClickHouse 支持参数化查询。例如

SELECT uniq(user_id) FROM table WHERE website = {name:String}

它允许安全地替换参数,而没有 SQL 注入的风险

curl https://clickhouse-server:8443/?param_name=upyachka -d 'SELECT uniq(user_id) FROM table WHERE website = {name:String}'

您甚至可以基于预准备查询为 clickhouse-server 创建自定义 API 处理程序。

在 21.12 版本中,我们引入了在查询中使用表和数据库参数的支持。这是通过 Identifier 表参数实现的

SELECT uniq(user_id) FROM {tbl:Identifier}

标识符参数也适用于 CREATE、DROP 和所有 DDL 查询。这是由 Nikolai Degterinskiy 实现的。

这对您有何帮助?

让 ClickHouse 完成繁重的工作,并确保您的脚本安全可靠。

Bool 数据类型

此功能在 21.12 版本中是实验性的。它由 Kevin Wan (MaxWk)hczhcz 的初步工作基础上实现,并由 Pavel Kruglov 审核。

ClickHouse 现在原生支持 Bool 数据类型。它允许在文本格式的数据导入和导出期间将值表示为 “true”/“false”。也可以使用设置 bool_true_representationbool_false_representation 将其调整为其他任何内容(例如,“yes” 和 “no”)。

这对您有何帮助?

原生布尔数据类型今天存在于其他经常与 ClickHouse 集成的数据库中,例如 PostgreSQL。 ClickHouse 中的 Bool 数据类型将使其与现有代码更兼容,并简化从其他数据库的迁移。

此外,它简化了从各种文本源的数据摄取。

使用表约束进行查询优化

此功能由 Nikita Vasilev 贡献。 Nikita 是 ClickHouse 最著名的贡献者之一。他于 2019 年开始将数据跳过索引引入 ClickHouse,然后在 2020 年继续推出 SSD 优化的键值字典,现在又为查询优化器贡献了新的进展。此功能由 Anton Popov 审核。

那么,有哪些优化呢? ClickHouse 已经允许为表指定约束

CREATE TABLE
(
    URL String,
    Domain String,
    CONSTRAINT validate CHECK isValidUTF8(URL) AND length(URL) BETWEEN 10 AND 10000,
    CONSTRAINT my_constraint CHECK Domain = domainWithoutWWW(URL)
) ...

约束在 INSERT 时进行检查。在此示例中,我们验证 URL 并检查 Domain 列是否实际包含 URL 的域名。

自 21.12 版本起,约束还可以自动优化您的查询!例如,如果您编写

SELECT count() FROM hits WHERE domainWithoutWWW(URL) = 'ghe.clickhouse.tech'

查询可以自动重写为

SELECT count() FROM hits WHERE Domain = 'ghe.clickhouse.tech'

因为 Domain 列更小且更易于压缩,所以读取速度更快,并且不需要从 URL 计算域名。

您唯一需要做的是启用 optimize_using_constraintsoptimize_substitute_columns 设置。

作为奖励,我们引入了一种新的约束类型:ASSUME

CONSTRAINT my_constraint ASSUME Domain = domainWithoutWWW(URL)

这种类型的约束不会在 INSERT 时检查任何内容,但仍会使用假设来优化查询。

它还可以进行逻辑推理,简化条件并删除被证明由约束满足的条件。

它由 convert_query_to_cnf 设置控制。您还可以启用 optimize_append_index。使用此设置,ClickHouse 将在表主键上派生更多条件。

这个想法非常强大,以至于我们忍不住添加了一个功能:假设索引

INDEX my_index (a < b) TYPE hypothesis GRANULARITY 1

表达式会被检查,结果(true/false)将作为索引写入以进行查询优化。

这对您有何帮助?

尤其是在具有许多复杂表的大型 ClickHouse 部署中,用户可能很难始终了解查询给定数据集的最佳方法。约束可以帮助优化查询,而无需更改查询结构本身。它们还可以使更改表变得更容易。

例如,假设您有一个包含 Web 请求的表,并且它包含一个 URL 列,其中包含每个请求的完整 URL。很多时候,用户会想知道顶级域名(.com、.co.uk 等),ClickHouse 提供了 topLevelDomain 函数来计算。如果您发现很多人都在使用此函数,您可能会决定创建一个新的物化列,为每个记录预先计算顶级域名。

您可以不告诉所有用户更改他们的查询,而是使用表约束来告诉 ClickHouse,每次用户尝试调用 topLevelDomain 函数时,都应将请求重写为使用新的物化列。

分块读取大型远程文件

ClickHouse 结合了快速查询引擎和高效数据存储。它还允许集成外部数据源以进行数据导入和导出,甚至可以动态处理外部数据集,而无需进行数据导入或预处理。

当使用 s3urlhdfs 表函数读取 ParquetORCArrow 格式的大型文件时,ClickHouse 现在将自动选择是立即读取整个文件还是增量读取部分文件。现在默认启用此功能,设置 remote_read_min_bytes_for_seek 控制何时从全部读取切换到分块读取。默认值为 1MiB。

ParquetORCArrow 是面向列的格式(与 ClickHouse Native 格式非常相似),现在即使从带有 url 表函数的远程 HTTP 服务器读取它们,我们也可以仅读取请求的列(将执行范围请求以跳过不需要的数据)。

此功能由 Kseniia Sumarokova 实现。

这对我们的 ClickHouse 用户有何帮助?

在以前的版本中,当使用 s3urlhdfs 表函数从远程位置读取 Arrow 格式的文件时,ClickHouse 始终会将整个文件读入内存。当文件较小时,这效果很好,但当文件较大时,会导致过多的内存使用或根本无法工作。通过此更改,ClickHouse 将分块读取大型文件以控制内存使用量,并且现在能够读取非常大的文件。

... 以及更多

阅读 完整更新日志,了解 21.12 “圣诞” 版本的完整礼品清单,这些礼品来自 ClickHouse 团队

分享此帖子

订阅我们的新闻资讯

随时了解功能发布、产品路线图、支持和云产品!
正在加载表单...
关注我们
X imageSlack imageGitHub image
Telegram imageMeetup imageRss image