ClickHouse 23.11 版本发布说明

发布时间:2024年01月07日

图片

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

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

我们非常激动地分享在23.11版本中的一系列令人惊叹的功能。

发布概要:

新增25个新功能

实现了24项性能优化

修复了70处bug

本文只概述部分闪亮新功能,包括但不仅限于:任意类型连接、fileCluster函数、keeper改进、表的异步加载、system.numbers上的索引、并发控制机制、对S3上请求的积极重试,以及比以往更小的二进制大小等等的相关的能力!还有... 其他很多... 更多(https://clickhouse.com/docs/en/whats-new/changelog#-clickhouse-release-2311-2023-12-06)。

新贡献者

与往常一样,我们热烈欢迎在23.11中出现的所有新贡献者!ClickHouse的流行很大程度上要归功于社区的共同努力。看到社区的壮大总是让人欣喜万分。

如果你在下面看到你的名字,请与我们联系... 但我们也想在Twitter等地方遇到你。

Andrej Hoos, Arvind Pj, Chuan-Zheng Lee, James Seymour, Kevin Mingtarja, Oleg V. Kozlyuk, Philip Hallstrom, Sergey Kviatkevich, Shri Bodas, abakhmetev, edef, joelynch, johnnymatthews, konruvikt, melvynator, pppeace, rondo_1895, ruslandoga, slu, takakawa, tomtana, xleoken, 袁焊忠

S3Queue已经正式可用

由Sergei Katkovskiy和Kseniia Sumarokova贡献

在23.8版本中,我们宣布了S3Queue表引擎的实验性发布,它极大的简化了S3的增量加载。这个新的表引擎允许你从S3中流式传输数据。随着文件被添加到存储桶,ClickHouse将自动处理这些文件,将它们插入到指定的表中。有了这个功能,用户可以设置简单的增量流水线,而无需编写额外的代码。

我们很高兴地宣布,自其实验性发布以来,此功能已经得到了明显提升,现在已经准备好投入生产使用!为了庆祝这一时刻,我们的YouTube明星Mark录制了一个视频:

图片

关注 ClickHouse 官方 B 站账号,持续收看技术视频和 Meetup 活动的录播视频。

列统计信息用于 PREWHERE

由Han Fei贡献

列统计信息是ClickHouse中一项新的实验性功能,它能够给查询优化提供更好的支持。您可以使用此功能让ClickHouse为具有MergeTree-family引擎的表的列创建(并自动更新)统计信息。这些统计信息存储在表的各个part中,以一个小的单独的statistics_(column_name).stat文件的形式存在,该文件是每个启用了统计信息的列的不同类型统计信息的通用容器文件。这确保了轻量级访问列统计信息。截至今天,唯一支持的列统计信息类型是t-digests。其他类型的支持在规划中。

列统计信息能使优化变得更好,一个典型的示例是:多阶段PREWHERE过滤中的列处理顺序。我们用一张图来描绘这个过程:

图片

图的左上角的查询由:具有多个AND连接的过滤条件组成的WHERE子句。ClickHouse有一种优化,试图评估具有尽可能少的扫描数据的过滤器。这个优化称为多阶段PREWHERE,它的基本思想是:我们可以按顺序读取过滤列,即逐列进行,并且在每次迭代中,仅检查包含至少一个“幸存”行(匹配的行)的块。每个过滤器要评估的块数量是单向递减的。

毫不奇怪,这种优化在评估产生最少幸存块的过滤器时效果最好 - 在这种情况下,ClickHouse只需要扫描少量的块来评估剩余的过滤器。当然,不可能知道每个过滤器生成的匹配行的块数,因此ClickHouse需要进行猜测,以确定执行过滤器的最佳顺序。使用列统计信息,ClickHouse能够更精确地估计匹配行/幸存块的数量,因此,多阶段PREWHERE作为一种变得更加有效的优化。

在这个示例中,ClickHouse利用列统计信息,自动的确定了列c2上的过滤条件是最有选择性的,即它丢弃了最多的块。因此,处理从c2开始。扫描列c2的所有块,并对每一行评估过滤谓词。接下来,对c3列进行过滤评估,但仅对在c2的相应块中具有至少一个匹配的行的块进行评估。因为c1列上的过滤条件是最不具选择性的,所以该列的块最后被处理。同样,仅扫描(并对每一行评估过滤谓词)那些从磁盘扫描的块,其中所有对应的PREWHERE列都有谓词匹配的块。

让我们通过一个具体的例子来演示这一点。

我们创建一个示例表并插入1000万行:

CREATE OR REPLACE TABLE example
(
    `a` Float64,
    `b` Int64,
    `c` Decimal64(4),
    `pk` String
)
ENGINE = MergeTree
ORDER BY pk;

INSERT INTO example SELECT
    number,
    number,
    number,
    generateUUIDv4()
FROM system.numbers
LIMIT 10_000_000

接下来,我们运行一个具有多个AND连接的过滤条件的查询,该查询位于WHERE子句中。请注意,我们禁用了PREWHERE优化:

SELECT count()
FROM example
WHERE b < 10 AND a < 10 AND c < 10
SETTINGS optimize_move_to_prewhere = 0

┌─count()─┐
│      10 │
└─────────┘

1 row in set. Elapsed: 0.057 sec. Processed 10.00 million rows, 240.00 MB (176.00 million rows/s., 4.22 GB/s.)
Peak memory usage: 162.42 KiB.

我们可以看到查询处理了240 MB的列数据。

现在我们使用(多阶段)启用了PREWHERE的相同查询:

SELECT count()
FROM example
WHERE b < 10 AND a < 10 AND c < 10

┌─count()─┐
│      10 │
└─────────┘

1 row in set. Elapsed: 0.032 sec. Processed 10.00 million rows, 160.42 MB (308.66 million rows/s., 4.95 GB/s.)
Peak memory usage: 171.74 KiB.

这次,查询处理了160MB的列数据。

接下来,我们启用列统计功能,并为表的三个列启用和实现基于t-digest的统计信息

SET allow_experimental_statistic = 1;
ALTER TABLE example ADD STATISTIC a, b, c TYPE tdigest;
ALTER TABLE example MATERIALIZE STATISTIC a, b, c TYPE tdigest;

运行启用列统计优化的示例查询:

SELECT count()
FROM example
WHERE b < 10 AND a < 10 AND c < 10
SETTINGS allow_statistic_optimize = 1

┌─count()─┐
│      10 │
└─────────┘

1 row in set. Elapsed: 0.012 sec. Processed 10.00 million rows, 80.85 MB (848.47 million rows/s., 6.86 GB/s.)
Peak memory usage: 160.25 KiB.

查询处理了80MB的列数据。

但这只是个开始。列统计信息还将用于其他重要的优化,比如连接重新排序或使低基数数据类型成为自动决策。

敬请关注!

并行窗口函数

由Dmitriy Novik贡献

任何使用SQL进行严肃数据分析的人都会赞赏窗口函数的价值。窗口函数在ClickHouse中自 v21.5以来就已经提供。PostgreSQL的文档对这种SQL功能进行了很好的总结:

窗口函数执行跨一组与当前行相关的表行的计算。这类似于可以使用聚合函数执行的计算类型。但与常规的聚合函数不同,窗口函数的使用不会导致将行组合成单个输出行 - 行保留其单独的标识。窗口函数能够访问查询结果的当前行以外的更多内容。

尽管窗口函数可以应用于一些非常复杂的问题,但大多数用户在需要执行诸如移动平均值(需要考虑多个行)或累计总和等简单操作时会遇到它们。由于这些特定查询,通常会在诸如Grafana之类的流行的可视化工具中使用,因此当它们的性能得到显着提高时,我们总是会很激动。在23.11中,ClickHouse通过确保窗口函数执行的可并行化,迈出了实现窗口函数的一大步。

这种并行化是通过利用窗口函数的固有分桶能力(分区)来执行的。当用户指定窗口函数应由列分区时,实际上为每个分区都创建了一个单独的逻辑窗口,即如果该列包含N个不同的值,则需要创建N个窗口。在v23.11中,可以有效地并行构建和评估这些分区。

举例,考虑以下查询,该查询使用NOAA天气数据集。

CREATE TABLE noaa
(
  `station_id` LowCardinality(String),
  `date` Date32,
  `tempAvg` Int32 COMMENT 'Average temperature (tenths of a degrees C)',
  `tempMax` Int32 COMMENT 'Maximum temperature (tenths of degrees C)',
  `tempMin` Int32 COMMENT 'Minimum temperature (tenths of degrees C)',
  `precipitation` UInt32 COMMENT 'Precipitation (tenths of mm)',
  `snowfall` UInt32 COMMENT 'Snowfall (mm)',
  `snowDepth` UInt32 COMMENT 'Snow depth (mm)',
  `percentDailySun` UInt8 COMMENT 'Daily percent of possible sunshine (percent)',
  `averageWindSpeed` UInt32 COMMENT 'Average daily wind speed (tenths of meters per second)',
  `maxWindSpeed` UInt32 COMMENT 'Peak gust wind speed (tenths of meters per second)',
  `weatherType` Enum8('Normal' = 0, 'Fog' = 1, 'Heavy Fog' = 2, 'Thunder' = 3, 'Small Hail' = 4, 'Hail' = 5, 'Glaze' = 6, 'Dust/Ash' = 7, 'Smoke/Haze' = 8, 'Blowing/Drifting Snow' = 9, 'Tornado' = 10, 'High Winds' = 11, 'Blowing Spray' = 12, 'Mist' = 13, 'Drizzle' = 14, 'Freezing Drizzle' = 15, 'Rain' = 16, 'Freezing Rain' = 17, 'Snow' = 18, 'Unknown Precipitation' = 19, 'Ground Fog' = 21, 'Freezing Fog' = 22),
  `location` Point,
  `elevation` Float32,
  `name` LowCardinality(String),
  `country` LowCardinality(String)
)
ENGINE = MergeTree
ORDER BY (country, date)


INSERT INTO noaa SELECT *
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/noaa/noaa_with_country.parquet')

在这里,可以使用简单的窗口函数,来计算每天每个国家的温度变化的平均值。这要求我们按国家分区(数据集中有214个国家)并按天排序。在计算变化的平均值时,我们考虑最后5个数据点。

SELECT
  country,
  day,
  max(tempAvg) AS temperature,
  avg(temperature) OVER (PARTITION BY country ORDER BY day ASC ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) AS moving_avg_temp
FROM noaa
WHERE country != ''
GROUP BY
  country,
  date AS day
ORDER BY
  country ASC,
  day ASC

这个简单函数的目的最好通过下面的简单的图示来解释。

图片

在 v23.11 之前,ClickHouse主要会并行执行此函数 - 特别是窗口函数除外。在查询不受其他因素(例如I/O)限制的情况下,这可能会限制性能。

在v23.10中,在具有96GiB RAM的12核机器上,此查询在总共10亿行数据上运行大约需要8.8秒。

SELECT
  country,
  day,
  max(tempAvg) AS avg_temp,
  avg(avg_temp) OVER (PARTITION BY country ORDER BY day ASC ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) AS moving_avg_temp
FROM noaa
WHERE country != ''
GROUP BY
  country,
  date AS day
ORDER BY
  country ASC,
  day ASC
LIMIT 10

┌─country─────┬────────day─┬─avg_temp─┬─────moving_avg_temp─┐
│ Afghanistan │ 1900-01-01 │    -81   │               -81 │
│ Afghanistan │ 1900-01-02 │   -145  │                 -113 │
│ Afghanistan │ 1900-01-03 │   -139  │ -121.66666666666667 │
│ Afghanistan │ 1900-01-04 │   -107  │                 -118 │
│ Afghanistan │ 1900-01-05 │    -44   │             -103.2 │
│ Afghanistan │ 1900-01-06 │     0    │               -86 │
│ Afghanistan │ 1900-01-07 │    -71   │  -84.33333333333333 │
│ Afghanistan │ 1900-01-08 │    -85   │  -74.33333333333333 │
│ Afghanistan │ 1900-01-09 │   -114  │  -70.16666666666667 │
│ Afghanistan │ 1900-01-10 │    -71   │  -64.16666666666667 │
└─────────────┴────────────┴──────────┴─────────────────────┘

10 rows in set. Elapsed: 8.515 sec. Processed 1.05 billion rows, 7.02 GB (123.61 million rows/s., 824.61 MB/s.)
Peak memory usage: 1.13 GiB.

从v23.11开始,通过并行执行每个分区来提高性能。同样,这最好通过一个简单的图示来描述。

图片

这里的实际收益取决于许多因素 - 至少有足够的分区和每个分区的工作,以使并行化显示出明显提升。这还假设查询不受其他因素的限制。在我们的示例中,我们在不需要进行任何操作的情况下,取得了10%以上的提升!

SELECT
  country,
  day,
  max(tempAvg) AS avg_temp,
  avg(avg_temp) OVER (PARTITION BY country ORDER BY day ASC ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) AS moving_avg_temp
FROM noaa
WHERE country != ''
GROUP BY
  country,
  date AS day
ORDER BY
  country ASC,
  day ASC
LIMIT 10

┌─country─────┬────────day─┬─avg_temp─┬─────moving_avg_temp─┐
│ Afghanistan │ 1900-01-01 │    -81   │               -81 │
│ Afghanistan │ 1900-01-02 │   -145  │                 -113 │
│ Afghanistan │ 1900-01-03 │   -139  │ -121.66666666666667 │
│ Afghanistan │ 1900-01-04 │   -107  │                 -118 │
│ Afghanistan │ 1900-01-05 │    -44   │             -103.2 │
│ Afghanistan │ 1900-01-06 │     0    │               -86 │
│ Afghanistan │ 1900-01-07 │    -71   │  -84.33333333333333 │
│ Afghanistan │ 1900-01-08 │    -85   │  -74.33333333333333 │
│ Afghanistan │ 1900-01-09 │   -114  │  -70.16666666666667 │
│ Afghanistan │ 1900-01-10 │    -71   │  -64.16666666666667 │
└─────────────┴────────────┴──────────┴─────────────────────┘

10 rows in set. Elapsed: 7.571 sec. Processed 1.05 billion rows, 7.02 GB (139.03 million rows/s., 927.47 MB/s.)
Peak memory usage: 1.13 GiB.

图片

??联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

文章来源:https://blog.csdn.net/ClickHouseDB/article/details/135442054
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。