DoubleCloud 即将停止运营。迁移到 ClickHouse 并享受限时免费迁移服务。立即联系我们 ->->

博客 / 产品

ClickHouse 21.12 新特性

author avatar
Alexey Milovidov 和 Christoph Wurm
2021 年 12 月 16 日

我们继续保持每月发布的节奏。21.12 圣诞节版本包含来自 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 或您的 Kafkas 和 Hadoops 一起使用。

更多信息.

用于 INSERT INTO 文件、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 ... 将创建与数据集中唯一月份数量一样多的文件。

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

这对您有什么帮助?

如果数据被分成多个文件,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。

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

这对您有什么帮助?

它允许您避免对报告进行后处理步骤。

添加对“标识符”表和数据库查询参数的支持

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 处理繁重的工作,并确保您的脚本安全可靠。

布尔数据类型

此功能在 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 原生格式非常相似),现在即使从带有url表函数的远程 HTTP 服务器读取,我们也可以只读取请求的列(将执行范围请求以跳过不需要的数据)。

此功能由Kseniia Sumarokova实现。

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

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

… 以及更多

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

分享此文章

订阅我们的时事通讯

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