技术流 | clickhouse如何加速merge

【本文作者:擎创科技 研发大拿 禹鼎侯,原文 公号 ClickHome】

本文翻译自:https://kb.altinity.com/altinity-kb-setup-and-maintenance/altinity-kb-aggressive_merges/

我们在使用clickhouse的过程中,往往会发现一个奇怪的现象:明明机器性能很强,如36core, 1TB内存,但是merge的时候资源却并不能充分利用。

原因何在呢?

大多数情况下,要想使资源充分利用上,需要改变并行度来进行实现。这里提供几个有效的配置,用来增加merge的并行度,提高merge的效率:

1、 background_pool_size

实际进行合并的线程。如果不进行查询,那么可以将所有核数都用来合并,比如将该参数设置为36,那么最大可以有36个线程将用来合并。

如果是副本模式的集群,那么所有的节点都需要相同的配置,并确保max_replicated_merges_in_queue的值相同。

2、background_merges_mutations_concurrency_ratio

每个线程分配多少个任务用于合并,默认是2。该参数的设置需要根据实际场景进行设置,如果小合并比较多,那么意味着一次合并并不能吃满一个CPU,那么此时一个线程分配两个合并任务,将有助于加速小part的merge,最典型的比如实时插入的场景。

如果每次插入的batch比较大,单个part比较大,那么意味着单次合并有可能将整个CPU跑满,此时如果还给单个线程分配2个合并任务,那么反而会拖累合并性能,此种场景建议值是1。

最终的合并任务个数 = background_pool_size * background_merges_mutations_concurrency_ratio。

您可以通过 SELECT metric, value FROM system.metrics WHERE metic LIKE '%background%'进行查看。

3、number_of_free_entries_in_pool_to_lower_max_size_of_merge

该配置属于merge_tree的设置。应该与background_pool_size一起更改。

当用于合并的线程任务池空闲的个数小于该值时,对比较大的part的合并暂时忽略不处理,这样做的目的是防止大part合并将线程池占满,无剩余资源用于小part合并,最终导致小part越积越多,出现"Too many parts(N)"错误。

要想充分发挥其威力,起到真正加速merge的作用,可以将该值设置为线程池的90%~95%。

此外,你可以设置下面这些参数配合使用:

  • 合并后多大的part可以称之为一个大part(由参数max_bytes_to_merge_at_max_space_in_pool控制,默认150G)

  • 在大合并中禁用直接IO(由参数min_merge_bytes_to_use_direct_io控制,默认10G),因为直接IO会绕过页缓存,因此通常会比较慢。

  • 在merge比较慢,但是网络传输比较快的副本集群上,可以尝试使用execute_merges_on_single_replica_time_threshold配置。该配置是仅在其中一个副本上执行merge, 另一个副本会隔execute_merges_on_single_replica_time_threshold时间后再去拉取同步副本数据。

  • 根据实际情况来决定,看是水平合并更好,还是垂直合并更佳。所谓水平合并,就是同时合并所有列。而垂直合并,是先merge表中的ORDER BY 列,然后再逐个merge其他列。这种合并方式会占用更少的内存,打开更少的文件,但与水平合并相比,需要更复杂的计算。

  • 如果表特别多,还可以为调度程序提供更多的资源。这里所说的调度程序,就是指分配merge和一些内部管理的组件,主要是调整background_schedule_pool_size和background_common_pool_size。

  • 检查表的schema,尤其是某些列的压缩算法,它虽然可以减小存储的空间,但是会严重影响merge的速度。

  • 在进行插入时,尽量一个批次多插入,使每个part本身就足够大。需要参考以下配置:min_insert_block_size_bytes / min_insert_block_size_rows / max_insert_block_size。

  • 检查是使用宽模式还是紧凑模式。宽模式指每个列都在一个单独的文件中,紧凑模式指多个列混合在一个文件中(可以从system.parts表查看)。默认情况下,min_bytes_for_wide_part=10,即part大于10(百万行),使用宽模式,否则使用紧凑模式。但有的时候,即使是较大的part(有特别多相对较小的列),使用紧凑格式也是有益的;或者相反,即使是较小的part(有少量的胖列),使用宽格式也是有益的。

  • 考虑使用最近发布的 clickhouse 版本 - 它们默认使用压缩标记,这有利于减少 i/o

以上只是一些理论层面的建议,对于这些配置的优化,所有的调整和性能优化都应通过一些可重现的 "基准 "来控制,这样你就能确保这些优化是否真的如我们所期望的那样。毕竟生产环境千变万化,有些优化并不一定绝对有效。同时还要监控系统资源,包括CPU,内存,IO以及zookeeper的使用情况,以及merge线程池的使用情况:

复制代码
select * from system.metrics where metric like '%PoolTask'

以上这些建议并不是无脑通用的。对于有些同时要求实时插入和大查询压力的系统,这些优化可能就会显得过于激进,因为上述调整其实是牺牲了查询性能的。因此,不同的设置模板适用于不同的集群场景,不能一概而论。

以下是一个优化设置模板,仅供参考:

复制代码
cat /etc/clickhouse-server/config.d/aggresive_merges.xml<clickhouse> <background_pool_size>36</background_pool_size> <background_schedule_pool_size>128</background_schedule_pool_size> <background_common_pool_size>8</background_common_pool_size> <background_merges_mutations_concurrency_ratio>1</background_merges_mutations_concurrency_ratio> <merge_tree>  <number_of_free_entries_in_pool_to_lower_max_size_of_merge>32</number_of_free_entries_in_pool_to_lower_max_size_of_merge>  <max_replicated_merges_in_queue>36</max_replicated_merges_in_queue>  <max_bytes_to_merge_at_max_space_in_pool>161061273600</max_bytes_to_merge_at_max_space_in_pool>  <min_merge_bytes_to_use_direct_io>10737418240</min_merge_bytes_to_use_direct_io> <!-- 0 to disable --> </merge_tree></clickhouse>
cat /etc/clickhouse-server/users.d/aggresive_merges.xml<clickhouse> <!-- on 22.8 that should be adjusted in both places - default profile and main config --><profiles><default><background_pool_size>36</background_pool_size><background_schedule_pool_size>128</background_schedule_pool_size><background_common_pool_size>8</background_common_pool_size><background_merges_mutations_concurrency_ratio>1</background_merges_mutations_concurrency_ratio></default></profiles></clickhouse>
相关推荐
卡尔特斯2 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源2 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole2 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫2 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide3 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户3721574261353 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源3 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
CoovallyAIHub4 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
Java中文社群4 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心4 小时前
从零开始学Flink:数据源
java·大数据·后端·flink