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

博客 / 工程

加速您的 ClickHouse 大数据加载 - 优化大数据加载速度

author avatar
Tom Schreiber
2023年10月18日

large_data_loads-p2-01.png

此博文是“加速您的 ClickHouse 大数据加载”系列的一部分

驶上赛道

在本关于加速大数据加载的三部分博文系列的第二部分中,我们将通过演示如何在使用相同硬件的情况下,将大型数十亿行插入的速度提高到默认设置的三倍,从而将第一篇博文中的理论付诸实践。第一篇。我们概述了一个公式,您可以使用它来确定最适合您的数据摄取用例的最佳块大小/并行度比率。最后,我们将通过利用 ClickHouse Cloud 的新 SharedMergeTree 表引擎以及轻松的水平集群扩展来突破速度限制。

请注意,我们这里只演示了一种调整场景,其中数据由 ClickHouse 服务器本身拉取。您可以此处阅读客户端将数据推送到 ClickHouse 的设置。

挑战

将 ClickHouse 用于大数据加载就像驾驶一辆高性能的一级方程式赛车🏎一样。大量的原始马力可用,您可以为您的大的数据加载达到最高速度。但是,为了获得最大的数据摄取性能,您必须根据(3)可用的马力数量(CPU 内核和 RAM)选择(1)足够高的档位(插入块大小)和(2)合适的加速级别(插入并行度)。

理想情况下,我们希望以**最高档位**和**全速加速**驾驶我们的赛车

但是,这两个性能因素之间存在冲突的权衡(加上与后台部分合并的权衡)。ClickHouse 服务器的可用主内存是有限的。较大的块使用更多主内存,这限制了我们可以使用的并行插入线程数。相反,较高的并行插入线程数需要更多主内存,因为插入线程数决定了并发创建的内存中插入块的数量。这限制了插入块的可能大小。此外,插入线程和后台合并线程之间可能存在资源竞争。大量配置的插入线程(1)创建更多需要合并的部分,并且(2)占用后台合并线程的 CPU 内核和内存空间。

我们的挑战是找到一个最佳点,即块大小足够大,并行插入线程数足够大,以达到最佳的插入速度。

实验

在以下部分中,我们将对这些块大小/并行度设置进行测试,并评估它们对摄取速度的影响。

测试数据

我们实验使用的数据来自PyPi 数据集(托管在 GCS 存储桶中)。它包含**653.3 亿行**,原始未压缩大小约为**14 TiB**。存储在 ClickHouse 表中的压缩数据大小约为**1.2 TiB**。

测试表和插入查询

对于这些测试,我们将尽快将此数据摄取到 ClickHouse Cloud 服务中的中,该服务由 3 台 ClickHouse 服务器组成,每台服务器有 59 个 CPU 内核和 236 GiB 的 RAM。我们将使用INSERT INTO SELECT 查询s3Cluster集成表函数(与 gcs 兼容)结合使用。large_data_loads-p2-02.png

我们将首先使用插入块大小插入线程的默认设置来摄取我们的大型数据集,然后使用不同的数字重复此加载以评估对加载时间的影响。

检查性能指标的查询

我们正在使用以下 SQL 查询对系统表进行检查,以检查我们在测试结果中可视化的插入性能指标

换档

large_data_loads-p2-03.png

为了说明插入块大小如何影响创建(并需要合并)的部分数量,我们在下面可视化了各种插入块大小(以行数表示)与单个数据块的(未压缩)平均内存大小及其相应的(压缩)单个数据部分的平均磁盘大小。这与写入存储的平均总部分数量叠加在一起。请注意,我们给出的是平均值,因为正如第一篇博文中所述,创建的块和部分很少精确地包含配置的行数或字节数,因为 ClickHouse 正在流式传输和逐行处理数据。因此,这些设置指定了最小阈值。

另外,请注意,我们在下一节中从不同数据导入测试运行的结果中获取了这些数字。

large_data_loads-p2-04.png您可以看到,我们配置的插入块大小越大,需要创建(以及合并)的分区就越少,以存储测试数据,约 1.2 TiB 的压缩表数据。例如,如果插入块大小为 100 万行,则磁盘上将创建 65000 个初始分区(平均压缩大小为 20 MiB)。而如果插入块大小为 8000 万行,则只会创建 817 个初始分区(平均压缩大小为 1.5 GiB)。

标准速度

下图显示了使用默认插入块大小约 100 万行但不同数量的插入线程的导入运行结果。我们展示了峰值内存使用量以及分区数量达到 3000(建议的用于高效查询的数量)所需的时间:large_data_loads-p2-05.png使用 ClickHouse Cloud 的默认设置 4 个导入线程(OSS 中默认没有并行导入线程),每个服务器的峰值主内存消耗为 7 GiB。从导入开始到最初创建的 65000 个分区合并到少于 3000 个健康的分区,需要花费 4 个多小时。在默认设置下,ClickHouse 试图在支持来自并发用户的并发任务方面提供良好的资源使用平衡。但是,一刀切的方法并不适用。我们的目标是调整仅供我们用于单一目的的专用服务:实现数据集插入的最高速度。

如果我们将并行插入线程的数量与 59 个可用 CPU 内核的数量相匹配,与较低的线程设置相比,达到 3k 活动分区所需的时间会增加。

使用 16 个插入线程可获得最短时间,这为与数据插入并发运行的后台分区合并线程留下了 59 个 CPU 内核中的大部分。

请注意,上图中的顶部蓝色水平条表示每个服务器的可用内存(236 GiB RAM)。我们可以看到,分别增加插入块大小和内存使用量(上图中的蓝色垂直条)的空间很大。

目前,我们在非常低的档位(每个初始分区只有 100 万行)上全力踩油门(最多 59 个插入线程),导致整体导入速度较低。现在,我们将在下一节中找到更好的档位和加速组合。

最高速度

large_data_loads-p2-06.png

我们尝试通过对这些插入速度因素进行不同系统组合的导入运行来确定插入块大小和插入线程数量的完美组合。下图显示了这些导入测试运行的结果,其中我们多次将插入块大小加倍(从100 万500 万1000 万2000 万4000 万,直到8000 万)。

large_data_loads-p2-07.png

对于每个块大小,我们都将插入线程的数量加倍(从 4 开始),直到峰值内存使用量(蓝色垂直条)几乎达到每个服务器的可用内存(蓝色水平条)。黄色圆圈表示从导入开始到所有最初创建的分区合并到少于 3000 个健康的分区所需的时间。

当我们数据集的 653.3 亿行由 32 个并行插入线程以 1000 万行的插入块大小导入时,我们达到了最高速度。对于我们 59 个 CPU 内核和 236 GiB RAM 的服务器大小,这是最佳点。这会导致适量的6500 个初始分区,可以由空闲的 27 个 CPU 内核(32 个内核用于并行读取和导入数据)在后台快速合并到少于 3000 个分区。使用 16 个或更少的插入线程时,插入并行度太低。使用 59 个插入线程时,1000 万行块大小不适合 RAM。

500 万行块大小适用于 59 个插入线程。但是,它创建了13000 个初始分区,并且没有为高效的后台合并保留任何专用的 CPU 内核,导致资源争用以及达到 3000 个活动分区所需的时间较长。使用 32 个和 16 个插入线程时,数据处理速度较慢,但合并速度更快,因为有更多专用的 CPU 内核可用于后台合并。4 个和 8 个插入线程在 500 万行块大小下无法创建足够的插入并行度。

2000 万行或更大的插入块大小会导致初始分区数量较少,但高内存开销将插入限制为数量较少的插入线程,从而导致插入并行度不足。

使用我们确定的最佳设置,我们使导入速度提高了近 3 倍。我们使用了完全相同的底层硬件,但更有效地利用它来进行数据导入,并且通过以半力(32 个插入线程)踩油门并使用尽可能高的档位(1000 万行块大小)来避免创建过多的初始分区。

一级方程式

我们知道,通过多次测试运行来确定大型数十亿行插入的完美设置是不切实际的。因此,我们为您提供此便捷公式,用于计算大型数据加载的最高速度的近似设置。

max_insert_threads:为插入线程选择大约一半的可用 CPU 内核(以保留足够的专用内核用于后台合并)。

peak_memory_usage_in_bytes:选择预期的峰值内存使用量;如果是隔离的导入,则可以使用所有可用 RAM,或者使用一半或更少(以预留空间供其他并发任务使用)。

然后
min_insert_block_size_bytes = peak_memory_usage_in_bytes / (~3 * max_insert_threads)

使用此公式,您可以将 min_insert_block_size_rows 设置为 0(以禁用基于行的阈值),同时将 max_insert_threads 设置为选定的值,并将 min_insert_block_size_bytes 设置为上述公式计算的结果。

突破 ClickHouse Cloud 的速度限制

large_data_loads-p2-08.png

使导入速度进一步提高的下一项措施是为我们的引擎增加更多马力,并通过添加更多服务器来增加可用 CPU 内核的数量。

结合其SharedMergeTree 表引擎,ClickHouse Cloud允许您自由地(并且快速地!)更改现有服务器的大小(CPU 和 RAM)或添加其他服务器。我们对我们的服务进行了后者操作,并使用不同数量的 ClickHouse 服务器(每个服务器都具有 59 个 CPU 内核和 236 GB RAM)导入我们的数据集。此图显示了结果large_data_loads-p2-09.png对于每个导入测试运行,我们都使用了上面部分中确定的最佳调整设置(32 个并行插入线程,插入块大小为 1000 万行)。

我们可以看到,导入吞吐量与 CPU 内核和 ClickHouse 服务器的数量成完美线性关系。这使我们能够根据需要快速运行大型数据插入。

它可以达到您想要的任何速度

ClickHouse Cloud 允许您轻松地通过添加更多 CPU 内核和服务器来线性扩展导入持续时间。因此,您可以根据需要快速运行大型导入。下图显示了这一点:large_data_loads-p2-10.png单个 ClickHouse Cloud 服务器(具有 59 个 CPU 内核和 236 GB RAM)以约 400 万行/秒的吞吐量在约 240 分钟内导入我们的 650 亿行数据集。上面的导入测试运行证明了线性可扩展性,因此我们预测了通过添加更多服务器可以如何提高吞吐量和导入时间。

总结

在本系列博客文章的第二部分中,我们提供了指导并演示了如何调整主要的插入性能因素,以大幅加快大型数十亿行插入的速度。在相同的硬件上,最高导入速度比默认设置快近 3 倍。此外,我们利用 ClickHouse Cloud 的无缝集群扩展功能使导入速度更快,并说明了如何通过扩展节点来根据需要快速运行大型数据插入。

希望您学习了一些加速大型 ClickHouse 数据加载的新方法。

在本系列的下一篇文章(也是最后一篇文章)中,我们将演示如何长时间可靠地增量加载大型数据集。

敬请期待!

立即开始使用 ClickHouse Cloud 并获得 300 美元的积分。在 30 天试用期结束时,继续使用按需付费计划,或联系我们以了解有关我们的基于容量的折扣的更多信息。访问我们的定价页面以了解更多详细信息。

分享此文章

订阅我们的时事通讯

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