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

博客 / 工程

监控异步插入

author avatar
Tom Schreiber
2024 年 1 月 4 日

介绍

在本篇关于 异步插入 的后续文章中,我们将提供监控异步插入的指南和查询。这有助于验证一切是否按您的设置正常工作。此外,还可以特别识别在 缓冲区刷新期间 发生的异步插入错误,这些错误是在 即发即弃模式 下执行的。

异步插入机制入门

提醒一下,异步插入通过在服务器端缓冲多个(可能很小的)插入,然后再创建新分区,从而自动控制分区创建频率。下图说明了这一点:monitoring_async_inserts_02.png 当 ClickHouse ① 接收异步插入查询时,查询的数据将 ② 立即写入内存缓冲区。异步地,当 ③ 下一个缓冲区刷新发生时,缓冲区的数据将 排序 并写入数据库存储作为分区。在缓冲区刷新之前,来自同一客户端或其他客户端的其他异步插入查询的数据可以收集在缓冲区中。因此,从缓冲区刷新创建的分区可能包含来自多个异步插入查询的数据。请注意,可能 存在 从单个缓冲区刷新创建的多个分区,并且可能 存在 同时运行的多个缓冲区。

相关系统表

ClickHouse 提供对自身的 基于 SQL 的可观察性。每个 ClickHouse 节点都在不断监控自身,并将指标、日志、跟踪和其他可观察性数据持续写入 系统表。这使我们能够简单地使用 SQL 和 ClickHouse 本身来深入了解 ClickHouse 数据处理机制,例如异步插入。总的来说,系统表是我们的核心工程师和支持工程师的头号故障排除工具。

此图列出了当 ClickHouse 接收和执行异步插入时收集的可观察性数据的系统表:monitoring_async_inserts_03.png ① 当 ClickHouse 接收和执行插入查询时,这将与执行统计信息一起 记录system.query_log 表中。

② 在 system.metrics 表中,您可以检查 PendingAsyncInsert 指标以获取当前处于缓冲状态并等待刷新的异步插入查询的数量。

system.asynchronous_insert_log 表记录所有缓冲区刷新事件。

④ 每当创建表分区时,该事件都会记录到 system.part_log 表中。

system.parts 表包含有关所有当前存在的表分区的信息。

在以下部分,我们将介绍和描述一些在这些上述系统表上执行的便捷查询,以深入了解异步插入的执行阶段。

请注意,这些查询假设是在 具有特定名称的集群 上执行的,通过使用 clusterAllReplicas 表函数。如果您没有使用 ClickHouse 的集群版本,您可以直接从您的单个节点查询这些表。

用于深入了解异步插入的查询

为了帮助调试,我们提供了一个简单的 脚本,它将以下所有查询创建为便捷的 参数化视图

分区创建

请记住,异步插入的主要目的是通过在 ClickHouse 服务器端缓冲多个(可能很小的)插入,然后再创建新分区,从而控制分区创建频率。

这里 是一个在 system.part_log 表(与 system.parts 联接以获取更多信息)上执行的查询,您可以使用它来仔细检查分区创建频率。 请记住,缓冲在异步插入缓冲区中的表行可能包含多个不同的 分区键 值,因此在缓冲区刷新期间,ClickHouse 为每个表分区至少创建一个新分区。

该查询配置了 4 个 CTE 标识符(db_nametable_namelast_x_minuteslast_m_parts_per_node_per_partition)。参数化视图 monitor_parts 与参数具有相同的标识符。

对于特定数据库和表,该查询列出了过去 x 分钟内每个集群节点 (n) 和每个表分区 (ptn) 的最新 m 个新建分区的创建时间 (write)、包含的 rows 和压缩大小 on disk

为了方便起见,我们还显示了每个分区的 (prev),表示自同一个集群节点上的同一个表分区上的上一个分区创建以来经过了多少时间。

这是一个针对 SELECT * FROM monitor_parts(db_name='default', table_name='upclick_metrics’, last_x_minutes=10, last_m_parts_per_node_per_partition=4) 视图查询的示例结果:monitoring_async_inserts_04.png 该结果显示了在过去 10 分钟内,每个集群节点(在一个三节点 ClickHouse Cloud 服务上)和每个表分区上最新创建的 4 个分区。由于我们的 示例目标表 没有使用分区键,因此 ptn 列为空。我们可以看到,在三个集群节点中的每一个节点上,每隔 30 秒就会创建一个新分区。这正是我们在基准测试中配置异步插入的方式之一 运行,缓冲区刷新时间为 30 秒。请记住,缓冲区 每个 节点都存在。

缓冲区刷新

如果前面的查询结果没有显示异步插入的预期分区创建频率,那么第一步调试方法就是检查缓冲区刷新的频率。

可以在这里找到一个查询,它连接了system.asynchronous_insert_logsystem.query_log 表。 请记住,每个集群节点、每个插入查询形状(不包括值子句/数据)以及每个设置都有一个独立的缓冲区。

该查询配置了 4 个 CTE 标识符 (db_nametable_namelast_x_minuteslast_m_flushes_per_node_per_shape_per_settings)。参数化视图 monitor_flushes 与参数具有相同的标识符。

对于特定数据库和表,该查询列出了过去 x 分钟内每个集群节点 (n)、每个查询形状 (q) ID 和每个查询设置 (s) ID 的最新 m 次缓冲区刷新信息。对于每次缓冲区刷新,我们列出了 flush 时间、rows 数以及刷新到磁盘的未压缩 data 量。为了方便起见,我们还显示了 (prev) 自上次在相同节点上对相同查询形状和设置进行刷新以来经过的时间。此外,我们还显示了每个插入查询形状 ID 的一个具体 sample_query 和与设置 ID 对应的 sample_settings

这是 SELECT * FROM monitor_flushes(db_name='default', table_name='upclick_metrics’, last_x_minutes=10, last_m_flushes_per_node_per_shape_per_settings=4) 视图查询的示例结果:monitoring_async_inserts_05.png 该结果显示了过去 10 分钟内每个集群节点(在三节点 ClickHouse Cloud 服务上)和每个查询形状和设置的最新 4 次缓冲区刷新。我们可以看到,在三个集群节点中的每一个节点上,每隔 30 秒都会进行一次缓冲区刷新。这与我们在具有 30 秒缓冲区刷新超时的基准运行之一相匹配。刷新时间与从之前的查询返回的部件创建时间相关。请注意,所有插入查询都具有与上面示例结果中所示相同的形状和设置。

缓冲区刷新期间的插入错误

在缓冲区刷新期间可能会发生插入错误。使用默认异步插入返回行为,查询发送者会收到详细的错误消息,而不是确认消息。但是,使用即发即弃模式,即使在稍后的缓冲区刷新期间对目标表的插入实际上成功与否,原始插入到该查询的缓冲区仍会成功确认给发送者。

这里是一个查询,用于事后查找缓冲区刷新期间的插入错误。该查询在system.asynchronous_insert_log 表上运行,并配置了 3 个 CTE 标识符 (db_nametable_namelast_x_minutes)。参数化视图 monitor_flush_errors 与参数具有相同的标识符。

该查询列出了每个集群节点 (n) 和错误 statusexception 消息,这些消息是过去 x 分钟内发生异常的最新缓冲区 flush 时间。以及其中一个查询的 query_id,该查询的缓冲数据在缓冲区刷新期间导致插入错误。您可以使用此 ID 查询(或连接)system.query_log 表,以获取有关特定查询的更多信息。

这是 SELECT * FROM monitor_flush_errors(db_name='default', table_name='upclick_metrics’, last_x_minutes=10) 视图查询的示例结果:monitoring_async_inserts_06.png 该结果显示了在过去 10 分钟内,每个集群节点(在三节点 ClickHouse Cloud 服务上)的两个缓冲区刷新期间发生了一些解析错误。

待处理刷新

最后,这里是一个查询,它检查PendingAsyncInsert 指标在system.metrics 表中的当前值,以获取每个集群节点当前缓冲的异步插入查询数量,这些查询的数据正在等待刷新。

这是一个示例查询结果:monitoring_async_inserts_07.png

场景

在本节中,我们将使用上一节中的一些查询来确定缓冲区刷新和部件写入频率的根本原因。

简单直接

当在目标表中未使用任何分区键,并且每个插入查询都具有相同的形状和设置时,我们会看到缓冲区将根据配置的刷新阈值设置进行刷新,并且缓冲区刷新和写入磁盘的部件之间存在 1:1 关系。这种情况发生在每个节点上。以下两个示例查询结果针对缓冲区刷新部件创建查询,演示了这一点:monitoring_async_inserts_08.png 在三节点 ClickHouse Cloud 服务上,我们在基准运行之一中使用 30 秒的缓冲区刷新时间配置了异步插入。我们看到,每个节点上每隔 30 秒都会进行一次缓冲区刷新,从而导致每个节点每隔 30 秒写入一个部件到磁盘。请查看上面两个查询结果中突出显示的行,其中对应缓冲区刷新和部件创建使用相同的颜色。

多个分区键

当在目标表中使用分区键时,通常不再存在(每个节点)缓冲区刷新和写入磁盘的部件之间的 1:1 关系。相反,每个缓冲区刷新可能会创建多个部件。接下来的两个示例查询结果显示了这一点:monitoring_async_inserts_09.png 上面两个查询结果中突出显示的行表明,在同一节点上,一次缓冲区刷新导致在同一节点上的同一时间写入三个部件。因为当缓冲区刷新时,缓冲区中的行包含三个不同的分区键值。

多个查询形状

因为每个插入查询形状(以及每个节点)都有一个独立的缓冲区,所以每个节点上可能会发生超过一个缓冲区刷新,这可能超过配置的缓冲区刷新阈值。这两个示例查询结果概述了这一点:monitoring_async_inserts_10.png 我们使用 30 秒的缓冲区刷新时间配置了异步插入。如上面 缓冲区刷新 查询结果中突出显示的两行所示,在下一个缓冲区刷新超时时,同一个节点上发生了两次缓冲区刷新。因为该节点收到了针对同一目标表但具有两个不同语法形状的插入查询,所以该节点上存在两个独立的缓冲区。如 写入磁盘的部件 查询结果中突出显示的两行所示,缓冲区刷新和写入磁盘的部件之间仍然存在 1:1 关系,因为在目标表中未使用任何分区键。

多个设置

与不同的查询形状类似,每个唯一插入查询设置集都有一个单独的缓冲区。这对于对同一表的不同数据启用不同的刷新阈值以及控制特定数据的资源使用情况非常有用。我们可以观察到以下混合缓冲区刷新周期:monitoring_async_inserts_11.png 上面 缓冲区刷新 查询结果中突出显示的两行表明,在同一个节点上,针对同一目标表存在两个独立且不同的刷新周期。因为该节点收到了针对同一目标表但具有两个不同设置的插入查询,特别是缓冲区刷新阈值设置,所以在该节点上存在两个具有独立刷新周期的缓冲区。写入磁盘的部件 查询结果中突出显示的两行表明,缓冲区刷新和写入磁盘的部件之间仍然存在 1:1 关系,因为在目标表中未使用任何分区键。

组合

可能存在使用分区目标表以及具有不同查询形状和设置的该表的异步插入的场景。这导致每个集群节点对每个不同的查询形状和设置集运行一个缓冲区。这会创建(至少)每个不同的分区键值,当这些缓冲区之一被刷新时,这些分区键值存储在缓冲区中包含的行中。我们提供的 缓冲区刷新写入磁盘的部件 自省查询将正确地指示这一点。

总结

在本博文中,我们提供了自省异步插入的指南和查询。您可以使用提供的查询来双重检查和排查异步插入配置问题。

立即开始使用 ClickHouse Cloud 并获得 300 美元的信用额度。在您的 30 天试用期结束时,您可以继续使用按需付费计划,或者联系我们,详细了解我们的基于容量的折扣。请访问我们的价格页面,获取详细信息。

分享这篇文章

订阅我们的时事通讯

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