ClickHouse 22.1版本新特性盘点

作者:Alexey Milovidov

原文链接:https://clickhouse.com/blog/en/2022/clickhouse-v22.1-released/

22.1 是我们新年的第一个版本。它包括来自 133 个贡献者的 2,599 个新提交,其中包括 44 个新贡献者:

13DaGGeR, Adri Fernandez, Alexey Gusev, Anselmo D. Adams, Antonio Andelic, Ben, Boris Kuschel, Christoph Wurm, Chun-Sheng, Li, Dao, DimaAmega, Dmitrii Mokhnatkin, Harry-Lee, Justin Hilliard, MaxTheHuman, Meena-Renganathan, Mojtaba Yaghoobzadeh, N. Kolotov, Niek, Orkhan Zeynalli, Rajkumar, Ryad ZENINE, Sergei Trifonov, Suzy Wang, TABLUM.IO, Vitaly Artemyev, Xin Wang, Yatian Xu, Youenn Lebras, dalei2019, fanzhou, gulige, lgbo-ustc, minhthucdao , mreddy017, msirm, olevino, peter279k, save-my-heart, tekeri, usurai, zhoubintao, 李扬。

不要忘记在您的服务器上运行SELECT * FROM system.contributors查看贡献者!

让我们描述一下 22.1 中最重要的新特性。

schema自动推导

以下面的查询为例:

SELECT * FROM url('https://datasets.clickhouse.com/github_events_v2.native.xz', Native,
$$
    file_time DateTime,
    event_type Enum('CommitCommentEvent' = 1, 'CreateEvent' = 2, 'DeleteEvent' = 3, 'ForkEvent' = 4,
                    'GollumEvent' = 5, 'IssueCommentEvent' = 6, 'IssuesEvent' = 7, 'MemberEvent' = 8,
                    'PublicEvent' = 9, 'PullRequestEvent' = 10, 'PullRequestReviewCommentEvent' = 11,
                    'PushEvent' = 12, 'ReleaseEvent' = 13, 'SponsorshipEvent' = 14, 'WatchEvent' = 15,
                    'GistEvent' = 16, 'FollowEvent' = 17, 'DownloadEvent' = 18, 'PullRequestReviewEvent' = 19,
                    'ForkApplyEvent' = 20, 'Event' = 21, 'TeamAddEvent' = 22),
    actor_login LowCardinality(String),
    repo_name LowCardinality(String),
    created_at DateTime,
    updated_at DateTime,
    action Enum('none' = 0, 'created' = 1, 'added' = 2, 'edited' = 3, 'deleted' = 4, 'opened' = 5, 'closed' = 6, 'reopened' = 7, 'assigned' = 8, 'unassigned' = 9,
                'labeled' = 10, 'unlabeled' = 11, 'review_requested' = 12, 'review_request_removed' = 13, 'synchronize' = 14, 'started' = 15, 'published' = 16, 'update' = 17, 'create' = 18, 'fork' = 19, 'merged' = 20),
    comment_id UInt64,
    body String,
    path String,
    position Int32,
    line Int32,
    ref LowCardinality(String),
    ref_type Enum('none' = 0, 'branch' = 1, 'tag' = 2, 'repository' = 3, 'unknown' = 4),
    creator_user_login LowCardinality(String),
    number UInt32,
    title String,
    labels Array(LowCardinality(String)),
    state Enum('none' = 0, 'open' = 1, 'closed' = 2),
    locked UInt8,
    assignee LowCardinality(String),
    assignees Array(LowCardinality(String)),
    comments UInt32,
    author_association Enum('NONE' = 0, 'CONTRIBUTOR' = 1, 'OWNER' = 2, 'COLLABORATOR' = 3, 'MEMBER' = 4, 'MANNEQUIN' = 5),
    closed_at DateTime,
    merged_at DateTime,
    merge_commit_sha String,
    requested_reviewers Array(LowCardinality(String)),
    requested_teams Array(LowCardinality(String)),
    head_ref LowCardinality(String),
    head_sha String,
    base_ref LowCardinality(String),
    base_sha String,
    merged UInt8,
    mergeable UInt8,
    rebaseable UInt8,
    mergeable_state Enum('unknown' = 0, 'dirty' = 1, 'clean' = 2, 'unstable' = 3, 'draft' = 4),
    merged_by LowCardinality(String),
    review_comments UInt32,
    maintainer_can_modify UInt8,
    commits UInt32,
    additions UInt32,
    deletions UInt32,
    changed_files UInt32,
    diff_hunk String,
    original_position UInt32,
    commit_id String,
    original_commit_id String,
    push_size UInt32,
    push_distinct_size UInt32,
    member_login LowCardinality(String),
    release_tag_name String,
    release_name String,
    review_state Enum('none' = 0, 'approved' = 1, 'changes_requested' = 2, 'commented' = 3, 'dismissed' = 4, 'pending' = 5)
$$)

在这个查询中,我们使用table functionurl导入数据。数据以文件扩展名为.native.xz的文件的形式发布在 HTTP 服务器上。这个查询最烦人的一点是我们必须指定这个文件的数据结构和格式。

在新版本 22.1 中,则不用如此复杂:

SELECT * FROM url('https://datasets.clickhouse.com/github_events_v2.native.xz')

比原来简单多了!这是怎么做到的呢?

首先,我们从文件扩展名中自动检测数据格式。这里是.native.xz,所以我们知道数据是经过xz(LZMA2)压缩,用Native格式来表示的。而Native格式中已经包含有关列的类型和名称的所有信息,我们只需读取和利用这些信息。

这个特性适用于以下格式:Native, Avro, Parquet, ORC,Arrow以及CSVWithNamesAndTypes, TSVWithNamesAndTypes

该特性也适用于以下表函数:s3, file, hdfs, url, s3Cluster, hdfsCluster.

该特性中包含了很多技巧:它不需要将整个文件读入内存,例如Parquet格式在文件末尾有元数据。因此,我们首先读取 header 以查找元数据所在的位置,然后进行范围请求以读取有关列及其类型的元数据,然后继续读取请求的列。如果文件很小,它将通过单个请求读取。

如果只从文件中提取数据结构而不进行数据处理,可以使用 DESCRIBE 查询:

DESCRIBE url('https://datasets.clickhouse.com/github_events_v2.native.xz')

数据结构也可以从JSONEachRowCSVTSVCSVWithNamesTSVWithNamesMsgPack, ValuesRegexp中自动推断。CSV支持Float64 或 String类型的推断 。JSONEachRow支持数组类型的推断,包括多维数组。数组中元素类型不一致时,会被自动推断成元组,Objects则被映射到Map数据类型。

如果格式中没有指定列名(如不带HeaderCSV),则使用c1, c2, …表示每一列。

文件格式可从扩展名中推断而来:csv, tsv, native, parquet, pb, ndjson, orc… 例如,.ndjson文件在 ClickHouse 中被识别为JSONEachRow格式,而.csv识别为无HeaderCSV格式,如果您要使用CSVWithNames格式,可以在query中显式指定格式。

我们支持“按需模式”查询。例如,自动检测到的TSV格式数据类型是字符串,但您可以使用::运算符优化查询中的类型:

SELECT c1 AS domain, uniq(c2::UInt64), count() AS cnt
  FROM file('hits.tsv')
  GROUP BY domain ORDER BY cnt DESC LIMIT 10

更方便的是,LineAsString格式RawBLOB也可以获得类型推断。试试这个查询,看看我更喜欢如何阅读我最喜欢的网站:

SELECT extractTextFromHTML(*)
    FROM url('https://news.ycombinator.com/', LineAsString);

schema自动检测也适用于创建Merge,DistributedReplicatedMegreTree表。创建第一个副本时,必须指定表结构。但是在创建所有后续副本时,您只需要CREATE TABLE hits ENGINE = ReplicatedMegreTree(...),而无需列出每一列,因为这些信息将从另一个副本复制。

此功能由Pavel Kruglov在Igor Baliuk的初始工作的启发下实现,并由ZhongYuanKai 添加。

clickhouse-client实时显示query资源占用

clickhouse-client是我最喜欢的 ClickHouse客户端。它是所有命令行工具的典范。

现在它可以直接在进度条中实时显示当前查询CPU 和内存的使用情况:

资源使用

对于分布式查询,它显示了每个主机的总内存使用量和最大内存使用量。

这个特性是通过Dmitry Novik实现的分布式metrics转发实现的。我已经将这些分布式metrics集成到clickhouse-client,现在可以使用Native ClickHouse协议在每个ClickHouse客户端中添加类似的信息。

副本粒度的并行查询

ClickHouse 是一个分布式 MPP DBMS。它可以向上扩展以使用一台服务器上的所有 CPU 内核,并向外扩展以使用集群中多个分片的计算资源。

但是每个分片通常包含多个副本。默认情况下,ClickHouse 在每个分片上仅使用一个副本的资源。例如,如果您有一个由 6 个服务器组成的集群,每个服务器上有 3 个分片和两个副本,那么查询将只使用三个服务器而不是全部六个。

有一个启用选项max_parallel_replicas,但该选项需要指定“采样键”,使用不方便且无法很好地扩展。

现在我们有一个选项来启用新的并行处理算法:allow_experimental_parallel_reading_from_replicas. 如果启用,副本将动态选择并在它们之间分配工作。

即使副本具有更少或更高数量的计算资源,它也能完美运行。即使某些副本是陈旧的,它也会给出完整的结果。

此功能由Nikita Mikhaylov实现

服务发现

在集群中添加或删除节点时,现在您不必在每台服务器上更新配置。只需在remote_server中使用<discovery>配置,副本就会自行注册:

<allow_experimental_cluster_discovery>1
</allow_experimental_cluster_discovery>

<remote_servers>
    <auto_cluster>
        <discovery>
            <path>/clickhouse/discovery/auto_cluster</path>
            <shard>1</shard>
        </discovery>
    </auto_cluster>
</remote_servers>

添加新副本时无需修改配置!

此功能由Vladimir Cherkasov实现。

列的稀疏编码

如果一列主要包含零,我们可以将其编码为稀疏格式并自动优化计算!

它是一种特殊的列编码,类似于LowCardinality,但它是完全透明的并且是自动工作的。

CREATE TABLE test.hits ...
ENGINE = MergeTree ORDER BY ...
SETTINGS ratio_of_defaults_for_sparse_serialization = 0.9

它可以更好地压缩数据并优化计算,因为稀疏列中的数据将在内存中以稀疏格式直接处理。

ClickHouse会在插入时根据column统计信息决定是否采用稀疏编码,并在后台merge时重新更新。

Anton Popov开发。

后续我们还想让 LowCardinality 编码自动进行,敬请期待!

ClickHouse的诊断工具[ ](https://clickhouse.com/blog/en/2022/clickhouse-v22.1-released/#diagnostic-tool-for-clickhouse)

这是来自 Yandex Cloud 团队的礼物。他们有一个工具来收集有关 ClickHouse 实例的报告,以提供所有需要的支持信息。他们决定将这个工具贡献给开源!

您可以在此处找到该工具:utils/clickhouse-diagnostics

Alexander Burmak开发.

第三方集成

22.1 中添加了许多新的集成:

与Hive集成作为 SELECT 查询的外部表引擎,由Taiyang Li提供并由Ksenia Sumarokova review。

与类似于S3的Azure Blob 存储集成,由Jakub Kuklis贡献并由Ksenia Sumarokova review。

支持类似于s3ClusterhdfsCluster表功能,由Yuzhichang Yu贡献,Nikita Mikhailov review。

统计函数

我希望你一直梦想着在 ClickHouse 中计算 Cramer 的 V 和 Theil 的 U 系数,因为现在我们已经为你准备好了这些函数。

:) SELECT cramersV(URL, URLDomain) FROM test.hits

0.98

:) SELECT cramersV(URLDomain, ResolutionWidth) FROM test.hits

0.27

它可以计算分类(离散)值之间的某种依赖关系。你可以这样想:有一个相关函数corr,但它只适用于线性依赖;有一个秩相关函数rankCorr,但它仅适用于有序值。现在有一些函数可以计算离散值。

开发人员:Artem TsyganovIvan BelyaevAlexey Milovidov

… 还有很多[ ](https://clickhouse.com/blog/en/2022/clickhouse-v22.1-released/#and-many-more)

阅读 22.1 版本的完整变更日志并遵循路线图