数仓调优实践丨多次关联发散导致数据爆炸案例分析改写

这篇具有很好参考价值的文章主要介绍了数仓调优实践丨多次关联发散导致数据爆炸案例分析改写。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文分享自华为云社区《GaussDB(DWS)性能调优:求字段全体值中大于本行值的最小值——多次关联发散导致数据爆炸案例分析改写》,作者: Zawami 。

1、【问题描述】

 

语句中存在同一个表多次自关联,且均为发散关联,数据爆炸导致性能瓶颈。

2、【原始SQL】

explain verbose
WITH TMP AS
(
    SELECT WH_ID
         , (IFNULL(SUBSTR(THE_DATE,1,10),'1900-01-01') || ' ' || STOP_TIME)::TIMESTAMP AS STOP_TIME
         , (IFNULL(SUBSTR(THE_DATE,1,10),'1900-01-01') || ' ' || '23:59:59')::TIMESTAMP AS MAX_ASD
      FROM DMISC.DM_DIM_CBG_WH_HOLIDAY_D
    WHERE IS_OPEN = 'Y'
      AND STOP_TIME IS NOT NULL
)
SELECT T1.WH_ID
     , T1.THE_DATE
     , T1.IS_OPEN
     , MIN(T2.STOP_TIME) AS STOP_TIME
     , MIN(T2.MAX_ASD) AS TODAY_MAX_ASD
     , MIN(T3.MAX_ASD) AS NEXT_MAX_ASD
FROM (SELECT WH_ID
           , THE_DATE
           , IS_OPEN
           , (IFNULL(SUBSTR(THE_DATE,1,10),'1900-01-01') || ' ' || STOP_TIME)::TIMESTAMP AS STOP_TIME
        FROM DMISC.DM_DIM_CBG_WH_HOLIDAY_D
     ) T1
LEFT JOIN TMP T2
ON T1.WH_ID = T2.WH_ID
AND T1.THE_DATE < T2.STOP_TIME

LEFT JOIN TMP T3
ON T1.WH_ID = T3.WH_ID
AND ADDDATE(T1.THE_DATE,1) < T3.STOP_TIME

GROUP BY T1.WH_ID, T1.THE_DATE, T1.IS_OPEN;

从SQL中不难看出,物理表HOLIDAY_D使用WH_ID为关联键,并使用其它字段做不等值关联。

3、【性能分析】

QUERY PLAN                                                                                                                                                                                                                                                     |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 id |                                    operation                                     |    E-rows     | E-distinct |   E-memory    | E-width |     E-costs                                                                                                    |
----+----------------------------------------------------------------------------------+---------------+------------+---------------+---------+-----------------                                                                                               |
  1 | ->  Row Adapter                                                                  |         51584 |            |               |      67 | 377559930171.36                                                                                                |
  2 |    ->  Vector Streaming (type: GATHER)                                           |         51584 |            |               |      67 | 377559930171.36                                                                                                |
  3 |       ->  Vector Hash Aggregate                                                  |         51584 |            | 16MB          |      67 | 377559929546.36                                                                                                |
  4 |          ->  Vector CTE Append(5, 7)                                             | 5699739636332 |            | 1MB           |      43 | 292063834485.54                                                                                                |
  5 |             ->  Vector Streaming(type: BROADCAST)                                |        757752 |            | 2MB           |      22 | 1474.87                                                                                                        |
  6 |                ->  CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d  [5, CTE tmp(1)] |        757752 |            | 1MB           |      22 | 1474.87                                                                                                        |
  7 |             ->  Vector Hash Left Join (8, 11)                                    | 5699739636332 |            | 107MB(6863MB) |      43 | 292063833010.67                                                                                                |
  8 |                ->  Vector Hash Right Join (9, 10)                                |     542231841 | 50         | 16MB          |      27 | 22365789.31                                                                                                    |
  9 |                   ->  Vector CTE Scan on tmp(1) t3                               |         31573 | 50         | 1MB           |      48 | 15155.04                                                                                                       |
 10 |                   ->  CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d               |         51584 | 50         | 1MB           |      19 | 556.58                                                                                                         |
 11 |                ->  Vector CTE Scan on tmp(1) t2                                  |         31573 | 50         | 1MB           |      48 | 15155.04                                                                                                       |

由于SQL非常慢,难以打出performance计划,我们先看verbose计划。从计划中我们看到,经过两次的关联发散,估计数据量达到了5万亿行;因为hash join根据WH_ID列进行关联,实际不会有这么多。所以调优的思路就是取消一些发散,让中间结果集行数变少。

4、【改写SQL】

分析SQL,可知发散是为了寻找所有STOP_TIME中大于本行THE_DATE的最小值。像这种每行都需要用到本行数据和所有数据的逻辑,或许可以使用窗口函数进行编写;但囿于笔者能力,先提供单次自关联的方法。

SQL改写如下:

explain performance
    WITH TMP AS
    (
        SELECT WH_ID
             , (IFNULL(SUBSTR(THE_DATE,1,10),'1900-01-01') || ' ' || STOP_TIME)::TIMESTAMP AS STOP_TIME
             , (IFNULL(SUBSTR(THE_DATE,1,10),'1900-01-01') || ' ' || '23:59:59')::TIMESTAMP AS MAX_ASD
          FROM DMISC.DM_DIM_CBG_WH_HOLIDAY_D
        WHERE IS_OPEN = 'Y'
          AND STOP_TIME IS NOT NULL
    )
    SELECT T1.WH_ID
         , T1.THE_DATE
         , T1.IS_OPEN
         , MIN(CASE WHEN T1.THE_DATE < T2.STOP_TIME THEN STOP_TIME ELSE NULL END) AS STOP_TIME
         , MIN(CASE WHEN T1.THE_DATE < T2.STOP_TIME THEN T2.MAX_ASD ELSE NULL END) AS TODAY_MAX_ASD
         , MIN(CASE WHEN ADDDATE(T1.THE_DATE, 1) < T2.STOP_TIME THEN T2.MAX_ASD ELSE NULL END) AS NEXT_MAX_ASD
    FROM (SELECT DISTINCT WH_ID
               , THE_DATE
               , IS_OPEN
            FROM DMISC.DM_DIM_CBG_WH_HOLIDAY_D
         ) T1
    LEFT JOIN TMP T2
    ON T1.WH_ID = T2.WH_ID
    GROUP BY
        T1.WH_ID
         , T1.THE_DATE
         , T1.IS_OPEN
    ;

经过改写,取消了一次自关联,SQL的中间结果集变小。在关联后,通过条件聚合来得到需要的值。

 id |                            operation                            |        A-time        |  A-rows  | E-rows | E-distinct |  Peak Memory   | E-memory |  A-width  | E-width | E-costs  
----+-----------------------------------------------------------------+----------------------+----------+--------+------------+----------------+----------+-----------+---------+----------
  1 | ->  Row Adapter                                                 | 7490.354             |    34035 |    200 |            | 70KB           |          |           |      58 | 15149.80 
  2 |    ->  Vector Streaming (type: GATHER)                          | 7488.129             |    34035 |    200 |            | 216KB          |          |           |      58 | 15149.80 
  3 |       ->  Vector Hash Aggregate                                 | [7481.430, 7481.430] |    34035 |    200 |            | [9MB, 9MB]     | 16MB     | [112,112] |      58 | 15137.30 
  4 |          ->  Vector Hash Left Join (5, 7)                       | [909.377, 909.377]   | 31204164 | 109803 |            | [2MB, 2MB]     | 16MB     |           |      34 | 3880.50  
  5 |             ->  Vector Sonic Hash Aggregate                     | [5.876, 5.876]       |    34035 |  34036 | 6807       | [3MB, 3MB]     | 16MB     | [51,51]   |      18 | 1127.67  
  6 |                ->  CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d | [0.199, 0.199]       |    34036 |  34036 |            | [792KB, 792KB] | 1MB      |           |      18 | 532.04   
  7 |             ->  CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d    | [40.794, 40.794]     |    25122 |  21960 | 19         | [1MB, 1MB]     | 1MB      | [59,59]   |      24 | 617.13   

从执行计划中可以看到,中间结果集大小已经在可接受的范围内。但是又看到聚合3千万数据使用了6s+的时间,这是过慢的,需要看执行计划中的DN信息寻找原因 。

                                                                                               Datanode Information (identified by plan id)                                                                                                
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1 --Row Adapter
        (actual time=7486.498..7490.354 rows=34035 loops=1)
        (CPU: ex c/r=107, ex row=34035, ex cyc=3668104, inc cyc=22468059912)
  2 --Vector Streaming (type: GATHER)
        (actual time=7486.466..7488.129 rows=34035 loops=1)
        (Buffers: shared hit=1)
        (CPU: ex c/r=660037, ex row=34035, ex cyc=22464391808, inc cyc=22464391808)
  3 --Vector Hash Aggregate
        dn_6083_6084 (actual time=7479.644..7481.430 rows=34035 loops=1) (projection time=4488.807)
        dn_6083_6084 (Buffers: shared hit=40)
        dn_6083_6084 (CPU: ex c/r=631, ex row=31204164, ex cyc=19718763112, inc cyc=22443886288)
  4 --Vector Hash Left Join (5, 7)
        dn_6083_6084 (actual time=48.009..909.377 rows=31204164 loops=1)
        dn_6083_6084 (Buffers: shared hit=36)
        dn_6083_6084 (CPU: ex c/r=43699, ex row=59157, ex cyc=2585141400, inc cyc=2725123176)
  5 --Vector Sonic Hash Aggregate
        dn_6083_6084 (actual time=5.177..5.876 rows=34035 loops=1)
        dn_6083_6084 (Buffers: shared hit=11)
        dn_6083_6084 (CPU: ex c/r=500, ex row=34036, ex cyc=17027544, inc cyc=17619064)
  6 --CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d
        dn_6083_6084 (actual time=0.043..0.199 rows=34036 loops=1) (CU ScanInfo: smallCu: 0, totalCu: 1, avrCuRow: 34036, totalDeadRows: 0)
        dn_6083_6084 (Buffers: shared hit=11)
        dn_6083_6084 (CPU: ex c/r=17, ex row=34036, ex cyc=591520, inc cyc=591520)
  7 --CStore Scan on dmisc.dm_dim_cbg_wh_holiday_d
        dn_6083_6084 (actual time=6.464..40.794 rows=25122 loops=1) (filter time=0.872 projection time=33.671) (RoughCheck CU: CUNone: 0, CUTagNone: 0, CUSome: 1) (CU ScanInfo: smallCu: 0, totalCu: 1, avrCuRow: 34036, totalDeadRows: 0)
        dn_6083_6084 (Buffers: shared hit=25)
        dn_6083_6084 (CPU: ex c/r=3595, ex row=34036, ex cyc=122362712, inc cyc=122362712)

从中可以看出,所有算子都只在一个DN上运行了。这可以视为严重的计算倾斜,若对单点性能有更高要求需要继续优化。查看DMISC.DM_DIM_CBG_WH_HOLIDAY_D表的定义,发现它是一个复制表(distribute by replication),在进行各层运算的时候只用其中一个DN来算。而在本SQL中,使用到这张表的时候,关联键都是WH_ID。

再查看调整分布列为WH_ID的倾斜情况:

select * from pg_catalog.table_skewness('DMISC.DM_DIM_CBG_WH_HOLIDAY_D', 'wh_id');

结果有23行,小于集群DN个数,且存在倾斜。但是本SQL需要使用该表的全量数据,故可以把这张表改为使用WH_ID作为分步键进行重分布。

由表分布方式为复制表导致的计算倾斜无法使用skew hint解决,可以改变物理表分布方式或者创建临时表来解决(复制表通常较小)。由于表在SQL中的使用情况和表的倾斜情况,不适合更改物理表分步键为WH_ID,故本例中试使用创建临时表指定重分布方式的办法解决。

DROP TABLE IF EXISTS holiday_d_tmp;
CREATE TEMP TABLE holiday_d_tmp WITH ( orientation = COLUMN, compression = low ) distribute BY hash ( wh_id ) AS ( SELECT * FROM DMISC.DM_DIM_CBG_WH_HOLIDAY_D );
EXPLAIN performance WITH TMP AS (
    SELECT
        WH_ID,
        ( IFNULL ( SUBSTR( THE_DATE, 1, 10 ), '1900-01-01' ) || ' ' || STOP_TIME ) :: TIMESTAMP AS STOP_TIME,
        ( IFNULL ( SUBSTR( THE_DATE, 1, 10 ), '1900-01-01' ) || ' ' || '23:59:59' ) :: TIMESTAMP AS MAX_ASD 
    FROM
        holiday_d_tmp 
    WHERE
        IS_OPEN = 'Y' 
        AND STOP_TIME IS NOT NULL 
    ) SELECT
    T1.WH_ID,
    T1.THE_DATE,
    T1.IS_OPEN,
    MIN ( CASE WHEN T1.THE_DATE < T2.STOP_TIME THEN STOP_TIME ELSE NULL END ) AS STOP_TIME,
    MIN ( CASE WHEN T1.THE_DATE < T2.STOP_TIME THEN T2.MAX_ASD ELSE NULL END ) AS TODAY_MAX_ASD,
    MIN ( CASE WHEN ADDDATE ( T1.THE_DATE, 1 ) < T2.STOP_TIME THEN T2.MAX_ASD ELSE NULL END ) AS NEXT_MAX_ASD 
FROM
    ( SELECT WH_ID, THE_DATE, IS_OPEN FROM holiday_d_tmp ) T1
    LEFT JOIN TMP T2 ON T1.WH_ID = T2.WH_ID 
GROUP BY
    T1.WH_ID,
    T1.THE_DATE,
    T1.IS_OPEN;

下面是对应的执行计划:

 id |                                      operation                                       |      A-time      |  A-rows  |  E-rows  | E-distinct |  Peak Memory   | E-memory | A-width | E-width | E-costs  
----+--------------------------------------------------------------------------------------+------------------+----------+----------+------------+----------------+----------+---------+---------+----------
  1 | ->  Row Adapter                                                                      | 673.495          |    34035 |    34032 |            | 70KB           |          |         |      58 | 68112.60 
  2 |    ->  Vector Streaming (type: GATHER)                                               | 671.103          |    34035 |    34032 |            | 216KB          |          |         |      58 | 68112.60 
  3 |       ->  Vector Hash Aggregate                                                      | [0.079, 672.724] |    34035 |    34032 |            | [1MB, 1MB]     | 16MB     | [0,114] |      58 | 67794.10 
  4 |          ->  Vector Hash Left Join (5, 6)                                            | [0.047, 76.395]  | 31205167 | 27587201 |            | [324KB, 485KB] | 16MB     |         |      34 | 8876.88  
  5 |             ->  CStore Scan on pg_temp_cn_5003_6_22022_139764371019520.holiday_d_tmp | [0.004, 0.098]   |    34036 |    34036 | 1          | [760KB, 792KB] | 1MB      |         |      18 | 1553.65  
  6 |             ->  CStore Scan on pg_temp_cn_5003_6_22022_139764371019520.holiday_d_tmp | [0.008, 3.253]   |    25122 |    22018 | 1          | [880KB, 1MB]   | 1MB      | [0,61]  |      24 | 1557.76  

从计划中我们可以看到,耗时比单个DN运算快了不少,当然这里没有算上创建临时表的时间约0.2s。

5、【调优总结】

在本案例中,因为实际执行SQL时间太长先看了verbose计划而非performance计划,发现中间结果集发散问题后,进行等价逻辑改写,把两个(等值-不等值)关联改为一个等值关联和条件聚合。之后,我们发现SQL因复制表存在计算倾斜问题,考虑SQL消费表数据的方式和表的统计数据,采用了使用临时表重新指定分布方式的方法,解决了计算倾斜问题,SQL从单点25min+优化到单点800ms。

 文章来源地址https://www.toymoban.com/news/detail-750698.html

点击关注,第一时间了解华为云新鲜技术~

 

到了这里,关于数仓调优实践丨多次关联发散导致数据爆炸案例分析改写的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • SSH登录Linux实例时多次连续错误输入密码导致用户锁定

     目录 问题描述: 解决思路: 解决方法: ssh登录服务器的时候,密码输出多次导致用户被锁定 系统提示“Maximum amount of failed attempts was reached”错误的处理方法 多次连续错误输入密码,触发系统PAM认证模块策略限制,导致用户被锁定。 重启ssh:service sshd restart 将用户的计数

    2024年02月15日
    浏览(8)
  • 得物社区亿级ES数据搜索性能调优实践

    得物社区亿级ES数据搜索性能调优实践

    2020年以来内容标注结果搜索就是社区中后台业务的核心高频使用场景之一,为了支撑复杂的后台搜索,我们将社区内容的关键信息额外存了一份到Elasticsearch中作为二级索引使用。随着标注业务的细分、迭代和时间的推移,这个索引的文档数和搜索的RT开始逐步上升。 下面是

    2024年02月05日
    浏览(10)
  • k8s+arm环境,clickhouse出现多次MEMORY_LIMIT_EXCEEDED导致pod crash

    k8s+arm环境,clickhouse出现多次MEMORY_LIMIT_EXCEEDED导致pod crash,可能是hugepage干扰内存分配器 1、修改文件 2、验证是否关闭

    2024年02月08日
    浏览(14)
  • Xcode升级导致关联库报错

    Xcode升级导致关联库报错

    想办法找到对应的库 然后到 Build Phases -- LinkBinary With Libraries中点击+,选择对应的framework即可,就像我工程的报错 Undefined symbol: _OBJC_CLASS_$_ADClient _OBJC_CLASS_$_ASIdentifierManager 缺失的库是AdSupport.framework 添加后再次编译即可通过 下面是Sqlite库和Zlib库的缺失最新的库导致的,一样添

    2024年02月14日
    浏览(14)
  • 多实例下定时任务执行多次chat 和实践

    定时任务在同一时间被执行了多次。发现是该微服务有多个实例。每个实例互不干扰都执行了。 任务执行时间过长,导致多个线程同时执行任务。这可能会发生在一个任务的执行时间大于任务执行周期的情况下。如果是这种情况,可以考虑将任务的执行时间缩短或者使用分布

    2024年02月01日
    浏览(10)
  • 实时数仓|基于Flink1.11的SQL构建实时数仓探索实践

    实时数仓主要是为了解决传统数仓数据时效性低的问题,实时数仓通常会用在实时的 OLAP 分析、实时的数据看板、业务指标实时监控等场景。虽然关于实时数仓的架构及技术选型与传统的离线数仓会存在差异,但是关于数仓建设的基本方法论是一致的。本文会分享基于 Flink

    2024年02月16日
    浏览(12)
  • 火山引擎Dataleap治理实践:如何降低数仓建设成本

    火山引擎Dataleap治理实践:如何降低数仓建设成本

    存储与计算资源是数仓建设的基础,也是数仓建设中的重要成本支出。而随着数仓建设规模逐渐扩大、时间跨度逐渐拉长,将不可避免的出现数据表、任务、字段的冗余。为了减轻资源负担,降低数仓维护成本,需要对数仓建设成本进行治理与优化。 针对数仓建设成本治理的

    2024年02月11日
    浏览(8)
  • 揭秘新一代云数仓技术架构与最佳实践

    从传统数仓到湖仓一体,历经三十多年发展,技术的浪潮快速迭代,以云原生数仓为中心的现代数据栈时代已然到来。 背后的核心的原因在于,企业正在加速走向数字化、智能化,对数据的应用也提出了全新要求,特别是对数据的实时分析、实时部署需求更加的强烈,而云数

    2024年02月09日
    浏览(15)
  • 实时数仓构建:Flink+OLAP查询的一些实践与思考

    今天是一篇架构分享内容。 以Flink为主的计算引擎配合OLAP查询分析引擎组合进而构建实时数仓 ,其技术方案的选择是我们在技术选型过程中最常见的问题之一。也是很多公司和业务支持过程中会实实在在遇到的问题。 很多人一提起实时数仓,就直接大谈特谈Hudi,Flink的流批

    2024年04月15日
    浏览(11)
  • 陈长城:NineData面向Doris实时数仓集成的技术实践

    在刚刚过去的北京Doris Summit Asia 2023,玖章算术技术副总裁陈长城受邀参加并做了《NineData面向Doris实时数仓集成的技术实践》报告。 玖章算术技术副总裁陈长城 从业界的报告中我们知道超过81%的企业使用了多云或混合云架构,超过70%的企业使用了多种数据类型,而对基础架构

    2024年02月05日
    浏览(7)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包