欢迎光临散文网 会员登陆 & 注册

CK SQL常用优化 一 COUNTD 优化

2023-08-10 03:15 作者:小仓朝qaq日  | 我要投稿

        在迭代速度较快业务中,为了扩展性,有很多情况下数仓会直接交付明细表,这时就需要查询时进行聚合,而COUNTD无疑是最耗时的常用聚合方式。

        我们知道ClickHouse是一个分布式数据库,由若干个分片组成。而我们进行去重计算时,最终会将数据聚合到某个节点进行计算,这会产生两个问题。一个是负载均衡问题,一个是网络传输问题,在分片数较少时问题不大(在前司时,看到很多私有化部署环境只有1/2个分片),而在分片数较多时会消耗大量时间。在数据准确性不敏感的情况下,一般会使用非精确去重比如uniqCombined 等,而在数据比较敏感的情况下,我们会不得不使用count distinct。有没有什么办法能让我们的countd性能与直接使用uniqCombined接近甚至超过呢?这就需要在建表以及查询时进行一些处理。

        假如我们在查一张明细表,比如一个uv字段,我们需要计算count(distinct userId),表中有包含userid的明细数据。这时我们可以在建CK表时,选择userId为分片键,进行建表。在查询时,我们将该count(distinct userId)进行下推,在local表中进行去重,去重后相加。不同公司的CK引擎都有自己的团队(比如字节跳动有4个CK团队,互不兼容),这个下推SQL的具体格式不确定,大概会长这样 select sum(innerM1) from cluster(default,view(select count(distinct userId) as innerM1 from table_local)) 。对应之前提到过countd性能差的原因,现在我们不需要跨分片去重,减少了大量数据传输的时间,也不需要集中在某一台机器中进行大量数据的去重,减少了负载均衡带来的问题。在我当前的业务场景中,120个分片,这个优化会提升查询速度近百倍。

    在应用该方法时需要注意,在查询多个分区数据时,是存在不同分片持有不同分区数据的情况的,因此使用该优化时我们需要指定分区(对应全量表)或者对按分区进行聚合(对应业务中按天聚合),万幸是实际使用中正常的PM只会提出这两种类型的需求。

    常见问题:

    1. 假如有两个字段都需要countd怎么办?

              答:建两张表

    2. 假如一定需要对某字段跨分区去重怎么办?

              答:让数仓建聚合表/说服PM

    3. 假如一定一定需要对某字段跨分区去重怎么办?、

              答: 下推后group by userId然后聚合,尽量减少负载均衡的问题。



CK SQL常用优化 一 COUNTD 优化的评论 (共 条)

分享到微博请遵守国家法律