激发大规模ClickHouse数据加载(1/3)性能和资源的考虑因素

图片

本文字数:4842;估计阅读时间:13 分钟

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

图片

简介

ClickHouse旨在快速、高效地利用硬件资源。如果允许,ClickHouse可以利用其运行的硬件,将数据加载得非常快速。或者您可以降低大数据加载的资源使用率,具体取决于您想要实现什么目标。在这个三部分的博客系列中,我们将提供必要的知识、指导和实现大数据加载的弹性和速度的最佳实践。本系列的第一部分通过描述ClickHouse中的基本数据插入机制及其控制资源使用和性能的三个主要因素来奠定基础。在第二篇文章中,我们将进入赛道,将大数据加载的速度调整到最大。在系列的最后一部分,我们将讨论使大量数据加载时,应对网络瞬时中断等问题更健壮性的措施。

让我们开始探讨基本的ClickHouse数据插入机制。

数据插入机制

以下图表概述了将数据插入到ClickHouse MergeTree引擎系列表中的一般机制:

图片

服务器接收一些部分数据(例如,来自插入查询),并从接收到的数据中①形成(至少)一个内存中的插入块(每个分区键)。块的数据被排过序,并实现表引擎特定的优化。然后,数据被压缩,并以new data part的形式②写入数据库存储。

请注意,还有一种情况,即客户端而不是服务器形成插入块(参考下面当客户端组织块时)

影响性能和资源使用的三个主要因素是:插入块大小、插入并行度和硬件大小。在本文的其余部分中,我们将讨论这些因素以及配置它们的方法。

插入块大小

对性能和资源使用的影响

图片

插入块大小影响ClickHouse服务器的磁盘文件I/O使用和内存使用。较大的插入块使用更多内存,但生成更大且更少的初始部分(part)。ClickHouse需要为加载大量数据创建的部分(part)越少,磁盘文件I/O和自动后台合并就越少。

插入块大小的配置方式取决于数据是如何被写入的。ClickHouse服务器本身是否拉取数据,还是由外部客户端推送?

在ClickHouse服务器拉取数据时的配置

在使用INSERT INTO SELECT语句与集成表引擎或表函数结合使用时,数据由ClickHouse服务器本身拉取:

图片

直到数据完全加载,服务器执行循环:

①拉取并解析下一部分数据,并从中形成一个内存数据块(每个分区键一个)。

②将块写入存储中的新部分。

转到①

在①中,数据部分的大小取决于插入块大小,可以使用两个设置来控制:

  • min_insert_block_size_rows(默认值:1,048,545百万行)

  • min_insert_block_size_bytes(默认值:256 MB)

当插入块中收集到指定数量的行,或达到配置的数据量时(以先到者为准),这将触发将块写入new part。插入循环继续从步骤①开始。

请注意,min_insert_block_size_bytes 值表示未压缩的内存块大小(而不是磁盘上压缩的part大小)。另外,创建的块和part很少精确包含配置的行数或字节数,因为ClickHouse是以流式传输和处理数据。因此,这些参数设置指定的是最小阈值。

当数据由客户端推送时的配置

取决于客户端或客户端库使用的数据传输格式和接口,内存中的数据块是由ClickHouse服务器本身还是由客户端形成的。这决定了块大小可以在何处以及如何进行控制。这进一步取决于是否使用同步或异步插入。

同步插入

当服务器组织块时

当客户端获取一些数据并以非native格式使用同步插入数据时(例如,JDBC驱动程序对插入使用RowBinary格式),服务器解析插入的数据并从中形成一个内存块(每个分区键一个),该块以部分(part)的形式写入存储:

图片

插入的行数自动控制块的大小。但是,块的最大大小(每个分区键)可以使用max_insert_block_size 设置进行配置。如果从插入查询的数据中形成的单个块包含的行数超过max_insert_block_size (默认值约为100万行),则服务器将创建额外的块和parts。

为了减少创建(和合并)部分(part)的数量,我们通常建议通过在客户端缓冲数据并批量插入数据,而不是进行许多小插入,从而发送较少但较大的插入。

当客户端组织块时

ClickHouse命令行客户端(clickhouse-client)以及一些特定于编程语言的库(如Go、Python和C++客户端)在客户端形成插入块并以native格式通过native接口将其发送到ClickHouse服务器,后者直接将块写入存储。

例如,如果使用ClickHouse命令行客户端插入一些数据:

./clickhouse client --host ...  --password …  \
 --input_format_parallel_parsing 0 \
 --max_insert_block_size 2000000 \
 --query "INSERT INTO t FORMAT CSV" < data.csv

那么客户端本身会解析数据并从数据中形成内存块(每个分区键一个),然后通过本机ClickHouse协议将其以native格式发送到服务器,服务器将块写入存储作为一个part:

图片

客户端的内存块大小(按行计)可以通过max_insert_block_size(默认值:1048545百万行)命令行选项进行控制。

请注意,在上面的示例命令行调用中禁用了并行解析。否则,clickhouse-client将忽略max_insert_block_size设置,而是将由并行解析产生的几个块压缩成一个插入块。

另请注意,客户端端的max_insert_block_size设置是特定于clickhouse-client的。您需要查看客户端库的文档和设置以查找类似的设置。

异步数据插入

或者,除了客户端端批处理,还可以使用异步插入。使用异步数据插入时,块始终由服务器形成,而不管使用的是哪个客户端、格式和协议:

图片

使用异步插入,从接收的插入查询的数据首先放入内存缓冲区(请参见上图中的①、②和③),当根据配置设置刷新缓冲区的数据时(例如,一旦收集到特定量的数据),服务器解析缓冲区的数据并从中形成内存块(每个分区键一个),然后将其以part的形式写入存储。如果单个块包含的行数超过max_insert_block_size rows,则服务器将创建额外的块和part。

更多Part=更多后台合并

配置的插入块大小越小,为大数据加载创建的初始部分(part)就越多,与数据写入同时执行的后台部分(part)合并就越多。这可能导致资源争用(CPU和内存)并要求在写入完成后需要额外的时间(以达到健康的part数量)。

ClickHouse将不断地将部分(part)合并成较大的部分,直到它们达到约150 GiB的压缩大小。此图显示了ClickHouse服务器如何合并部分:

图片

单个ClickHouse服务器利用多个后台合并线程执行并发的part合并。每个线程执行循环:

①决定下一个要合并的part,并将这些部分加载到内存中作为块。

②将内存中加载的块合并成一个较大的块。

③将合并的块写入磁盘上的新part。

转到①

请注意,ClickHouse不一定一次将整个要合并的部分(part)加载到内存中。为了减少内存消耗(以牺牲合并速度为代价),所谓的垂直合并基于块的块的部分(part)而不是一次性进行。此外,请注意,增加CPU核心数和RAM大小会增加后台合并吞吐量。

会被合并的part是被标记为非活动状态的part,并在可配置的几分钟后最终删除。随着时间的推移,这将创建一个合并部分的树。因此称为合并树(merge tree)表:

图片

插入并行性

对性能和资源使用的影响

图片

ClickHouse服务器可以并行处理和插入数据。插入并行性的级别影响ClickHouse服务器的写入吞吐量和内存使用。并行加载和处理数据需要更多的主内存,但由于数据处理更快,摄取吞吐量增加。

插入并行性的级别如何配置再次取决于数据的写入方式。

在ClickHouse服务器拉取数据时的配置

一些集成表函数(如s3、url和hdfs)允许通过glob模式指定要加载的文件名集。当glob模式匹配多个现有文件时,ClickHouse可以跨文件在和内部并行化读取,并通过利用并行运行的插入线程(每个服务器)并行插入数据到表中:

图片

直到所有文件的所有数据都被处理,每个插入线程执行一个循环:

① 获取未处理文件数据的下一部分(数据大小基于配置的块大小)并从中创建一个内存数据块。

②将块写入存储中的新part。

转到①。

这种并行插入线程的数量可以通过max_insert_threads设置进行配置。默认值为OSS为1,ClickHouse Cloud为4。

在存在大量文件的情况下,通过多个插入线程的并行处理效果很好。它可以充分使用CPU核心和网络带宽(用于并行文件下载)。在只加载到表中的少量大文件的情况下,ClickHouse会自动建立高级别的数据处理并通过为每个插入线程生成用于在大文件中并行读取(下载)更多不同范围的额外读取器线程,以优化网络带宽使用。对于高级读取器,max_download_threads和max_download_buffer_size可能会有所帮助。此机制目前已实现为s3和url表函数。此外,对于对于无法进行并行读取的文件,为了增加吞吐量,ClickHouse通过异步方式预读数据。

并行服务器

一些具有用于并行加载多个文件的glob模式的集成表函数也存在集群版本,例如s3Cluster、hdfsCluster和urlCluster。通过在多个服务器上利用前面提到的多个并行插入线程,这些表函数进一步提高了插入并行性的级别:

图片

最初接收插入查询的服务器首先解析glob模式,然后动态地将每个匹配文件的处理分派给其他服务器(以及自身)。

在客户端推送数据时的配置

ClickHouse服务器可以同时接收和执行插入查询。客户端可以通过运行并行的客户端端线程来利用这一点:

图片

每个线程执行一个循环:

①获取下一部分数据并从中创建一个插入。

②将插入发送到ClickHouse(并等待插入成功的确认)。

转到①

或者,也可以使用多个客户端同时将数据并行发送到ClickHouse:

图片

并行服务器

在ClickHouse Cloud中,插入会均匀分布在多个ClickHouse服务器上,并使用负载均衡器。传统的共享无关ClickHouse集群可以使用分片和分布式表的组合,以在多个服务器上平衡插入的负载:

图片

硬件规模

对性能的影响

图片

可用的CPU核心数量和RAM大小影响

  • 支持的 Part 的初始大小

  • 插入并行性的可能级别

  • 后台部件合并的吞吐量

因此,影响整体写入吞吐量。

CPU核心数量和RAM大小的更改容易程度取决于摄取是在ClickHouse Cloud还是传统的共享无关ClickHouse集群中进行的。

传统的共享无关ClickHouse集群

在传统的共享无关ClickHouse集群中,数据存储在每个服务器上:

图片

添加额外的服务器需要手动进行配置更改,并且比在ClickHouse Cloud中花费更多时间。

总结

您可以通过允许ClickHouse的数据插入机制充分利用其运行的硬件,使其以惊人的速度加载数据。或者,您可以降低大数据加载的资源使用量。这取决于您的数据加载场景是什么。为此,我们探讨了ClickHouse的数据插入机制的工作方式,以及您如何控制和配置ClickHouse中大数据加载的三个主要性能和资源使用因素:插入块大小插入并行性硬件规模

有了这个基础,我们为接下来的两篇文章设定了背景,将这些知识转化为快速和有弹性的大数据加载的最佳实践。在本系列的下一篇文章中,我们将进入赛车场,使大数据插入速度比默认设置快3倍。在相同的硬件上。

Meetup 活动报名通知

好消息:ClickHouse Shenzhen User Group第1届 Meetup 已经开放报名了,将于2024年1月6日在深圳南山区海天二路33号腾讯滨海大厦举行,扫码免费报名

图片

图片

​​联系我们

手机号:13910395701

邮箱:[email protected]

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

猜你喜欢

转载自blog.csdn.net/ClickHouseDB/article/details/134978458