clickhouse去重数量语句_这会是ClickHouse解决数据一致性的新法宝吗?

本文探讨了ClickHouse在处理数据一致性时的问题,特别是使用FINAL查询进行数据去重的性能问题。在旧版本中,FINAL查询会导致查询速度大幅下降,但在v20.5.2.7-stable及以后版本,引入了多线程支持,提升了FINAL查询的性能。通过对不同版本的ClickHouse进行测试,发现新版本的FINAL查询在性能上有所提升,但仍存在部分串行操作。文章建议根据具体业务数据进行测试以评估其效果。
摘要由CSDN通过智能技术生成

大家都知道,由于 MergeTree 的实现原理导致它只能支持数据的最终一致性。什么?你不知道?请进传送门。这导致我们在使用 ReplacingMergeTree、SummingMergeTree 这类表引擎的时候,会出现短暂数据不一致的情况。

在某些对一致性非常敏感的场景,通常有这么几种解决方案。

一种是在写入数据后,立刻通过 

OPTIMIZE TABLE PARTITION part FINAL

强制触发新写入分区的合并动作。

一种是通过 GROUP BY 查询 + 过滤实现,可以参考我先前的文章 传送门2号。

还有一种是通过 FINAL 查询实现,即在查询语句后增加 FINAL 修饰符,这样在查询的过程中将会执行 Merge 的特殊逻辑(例如数据去重,预聚合等)。

但是这种方法基本没有人使用,因为在增加 FINAL 之后,我们的查询将会变成一个单线程的执行过程,查询速度非常慢。

但是在最新的 MaterializeMySQL 中,消费同步 binlog 的表使用了 ReplacingMergeTree,而它实现数据去重的方法就是使用了 FINAL 查询,难道不怕慢吗?不知道 MaterializeMySQL ? 请进传送门3号。

原来在 v20.5.2.7-stable 版本中,FINAL 查询进行了优化,现在已经支持多线程执行了,并且可以通过 max_final_threads 参数控制单个查询的线程数。https://github.com/ClickHouse/ClickHouse/pull/10463

支持了多线程的 FINAL 查询到底性能如何呢? 我们就来试试看吧。

这里直接使用 Yandex 提供的测试数据集 hits_100m_obfuscated,它拥有 1亿 行数据,105个字段,DDL示意如下:

ATTACH TABLE hits_100m_obfuscated(    `WatchID` UInt64,     `JavaEnable` UInt8,     `Title` String,     `GoodEvent` Int16,     `EventTime` DateTime,     ... )ENGINE = ReplacingMergeTree()PARTITION BY toYYYYMM(EventDate)ORDER BY (CounterID, EventDate, intHash32(UserID), EventTime)SAMPLE BY intHash32(UserID)

我使用了两台 8c 16g 的虚拟机,分别安装了19.17.4.11 和 20.6.3.28 两个版本的 CH 进行对比。

首先在 19.17.4.11 中执行普通的语句:

select * from hits_100m_obfuscated WHERE EventDate = '2013-07-15' limit 100100 rows in set. Elapsed: 0.595 sec.

接近0.6秒返回,它的执行日志如下所示:

Expression Expression  ParallelAggregating   Expression × 8    MergeTreeThread

可以看到这个查询有8个线程并行查询。

接下来换 FINAL 查询:

select * from hits_100m_obfuscated FINAL WHERE EventDate = '2013-07-15' limit 100100 rows in set. Elapsed: 1.406 sec.

时间慢了接近3倍,然后看看 FINAL 查询的执行日志:

Expression Expression  Aggregating   Concat    Expression     SourceFromInputStream

先前的并行查询变成了单线程,所以速度变慢也是情理之中的事情了。

现在我们换到 20.6.3.28 版本执行同样的对比查询

首先执行普通的不带 FINAL 的查询:

select * from hits_100m_obfuscated WHERE EventDate = '2013-07-15' limit 100 settings max_threads = 8100 rows in set. Elapsed: 0.497 sec.

返回时间很快,在 CH 新版本中已经实现了 EXPLAIN 查询,所以查看这条 SQL 的执行计划就很方便了:

explain pipeline select * from hits_100m_obfuscated  WHERE EventDate = '2013-07-15' limit 100  settings max_threads = 8(Union)Converting × 8  (Expression)  ExpressionTransform × 8    (Limit)    Limit 8 → 8      (Expression)      ExpressionTransform × 8        (ReadFromStorage)        MergeTreeThread × 8 0 → 1

很明显的,该SQL将由8个线程并行读取 part 查询。 

现在换 FINAL 查询:

select * from hits_100m_obfuscated final WHERE EventDate = '2013-07-15' limit 100  settings max_final_threads = 8100 rows in set. Elapsed: 0.825 sec.

查询速度没有普通的查询快,但是相比之前已经有了一些提升了,我们看看新版本 FINAL 查询的执行计划:

explain pipeline select * from hits_100m_obfuscated final WHERE EventDate = '2013-07-15' limit 100  settings max_final_threads = 8(Union)Converting × 8  (Expression)  ExpressionTransform × 8    (Limit)    Limit 8 → 8      (Expression)      ExpressionTransform × 8        (Filter)        FilterTransform × 8          (ReadFromStorage)          ExpressionTransform × 8            ReplacingSorted × 8 6 → 1              Copy × 6 1 → 8                AddingSelector × 6                  ExpressionTransform                    MergeTree 0 → 1                      ExpressionTransform                        MergeTree 0 → 1                          ExpressionTransform                            MergeTree 0 → 1                              ExpressionTransform                                MergeTree 0 → 1                                  ExpressionTransform                                    MergeTree 0 → 1                                      ExpressionTransform                                        MergeTree 0 → 1

可以看到新版本 FINAL 查询的执行计划有了很大的变化。 在这条 SQL 中,从ReplacingSorted 这一步开始已经是多线程执行了。


不过比较遗憾的是,目前读取 part 部分的动作还是串行的。在这里例子中可以看到,这张表有6个分区被依次加载了。

好了,现在总结一下:

  1. 从 v20.5.2.7-stable 版本开始,FINAL 查询执行并行执行了

  2. 目前读取 part 部分的动作依然是串行的

  3. 总的来说,目前的 FINAL 相比之前还是有了一些性能的提升

最后的最后,FINAL 查询最终的性能和很多因素相关,列字段的大小、分区的数量等等都会影响到最终的查询时间, 所以大家还是需要基于自己的业务数据多加测试。

如果这篇文章对你有帮助,欢迎 点赞、转发、在看 三连击 :)

欢迎大家扫码关注我的 公众号和视频号 : ClickHouse的秘密基地 62d65bf8aaf271a4afd16a6dda803588.png nauu的奇思妙想 2abd61a027237a33cbb228a7845cdb21.png 往期精彩推荐:【专辑】ClickHouse的资讯手札【专辑】ClickHouse的原理巩固【专辑】ClickHouse的经验分享
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值