GaussDB(DWS)性能调优:性能问题闭环总结(一)——关联慢

举报
O泡果奶~ 发表于 2023/12/29 17:29:07 2023/12/29
【摘要】 本文是作者结合实际调优案例总结梳理出来的一些常用SQL性能优化方法,主要从四个方面(表扫描慢、关联慢、聚合慢、不可向量化)来分析,本篇重点介绍关联慢这一部分

主要从四个方面来分析,
image.png

一、关联慢

1、关联倾斜优化

业务问题

如下图所示,SQL执行性能瓶颈在于关联(发生数据倾斜),导致执行时间达到16min(该案例并非去HANA过程中发生的,而是从别处拿来讲解的案例)
image.png

分析思路

关联过程中,因为**关联条件中不包含表的分布键,可能会发生表关于关联条件重分布这一过程(也有可能直接广播,优化器会根据估算代价决定)。因此,会产生这样一种情况:关联条件中某个字段重复值过多,进而导致重分布时,数据分布产生倾斜(不同DN上数据量相差10% 即判定为数据倾斜)**,
关联倾斜的后果是:某个DN会因为数据量过大而成为语句执行的性能瓶颈
解决措施:

  • 找出关联条件中重复值较多的那个字段以及重复值
    重复值判断方法:
select count(1),report_item_id from fin_dmr_ebg.dm_ebg_reg_kpi_sum_w_f
where 过滤条件
group by 2
order by 1 desc
  • 在当前层(即发生关联这一层查询中)使用hint: /+skew(表名(字段名)(重复值))/
    具体使用方法可以看 https://support.huaweicloud.com/intl/zh-cn/performance-dws/dws_10_0029.html
    优化后,如下图所示,从执行计划中看出,运行倾斜问题得到了缓解
    image.png
    这两个问题解决后,语句执行性能变好,由992.835s变为173.7s

小结

DWS中一般默认将skew_option设置为normal(采用激进策略。对于不确定是否出现倾斜的场景,认为存在倾斜,并进行相应优化),因此,常规情况下,优化器能较好地避免数据倾斜情况,但不排除一些特殊情况导致优化器并未识别到。

2、调整关联顺序以避免关联倾斜

业务问题

该SQL语句执行时存在数据倾斜的问题,影响语句执行效率

分析思路

image.png
首先,查看语句执行计划,计划信息的SQL Diagnostic Information显示id=4那一层DN上最大数据20w,最小数据量5000+,证明发生了数据倾斜的问题,然后观察上边那一层出现Join(关联),证明是关联时数据倾斜
然后,针对该SQL这一点进行优化,一般来说,DWS优化器能够识别倾斜并进行相应优化(例如图中的PART … PART …),但可能也无法解决问题。
此时,可以修改关联顺序,先和表geo关联,因为数据倾斜可能是在关联其他表过程中发生的
在DWS中,引入guc参数leading,来指定join顺序,该参数有两种使用方式:

  • leading(join_table_list) 仅指定join顺序,不指定内外表顺序
  • leading((join_table_list)) 同时指定join顺序和内外表顺序,内外表顺序仅在最外层生效。如leading((a b)),则表a为外表,表b为内表。

使用过程中需要注意

  • list中的表必须在当前层或提升的子查询中存在
  • list中的表在当前层或提升的子查询中必须是唯一的。如果不唯一,需要使用不同的别名进行区分。
  • 同一个表只能在list里出现一次
  • 如果表存在别名,则list中的表需要使用别名

言归正传,让基表ship先和geo关联,再和大表dtl关联,最后再和表org关联(因为org在SQL语句中仅和表dtl有关联关系),此时利用hint来实现这一优化过程,hint需要加在当前层(含有这些表关联的那一层)

/*+ leading((ship geo) dtl)*/ 

该SQL经过优化后,执行时间降低了800ms左右,其执行计划如下图所示:
image.png
基表先和小表geo关联,缓解了原始SQL中存在数据倾斜问题,同时也降低了大数据量的REDISTRIBUTE关联

小结

SQL语句执行过程中,关联过程中(尤其是存在多重关联,如果某层关联能够减少大部分数据量,要利用hint将该层关联提到其能达到的最底层,以减少关联数据量。

3、避免Nest Loop算子引起的性能瓶颈

业务问题

SQL语句执行性能差,语句计划中存在Nest Loop算子引发性能瓶颈

分析思路

DWS中,Hash Join 的性能一般要优于 Nest Loop,因此,发现SQL语句执行慢并且执行计划中存在Nest Loop算子时通常要进行规避,一般导致Nest Loop出现的情况有三种

两表无关联条件(笛卡尔积)

该情况比较简单,如果关联中仅有这两张表则无法优化,只能走Nest Loop算子;若存在多张表,则可以通过调整关联顺序,以避免无关联条件的情况,若无法避免则也只能走Nest Loop算子

优化器走Index Scan+Nest Loop

image.png
上图因为性能问题,无法打出performance执行计划,从verbose执行计划中看到存在Index Scan+Nest Loop,此时,大致可以判断问题出在这里,原因是:优化器错误估算表的行数,导致Index Scan查询时因为频繁利用索引导致开销增大,效果不如全表扫描
此时可以利用hint来进行避免

设置 hint   /*+set [global](enable_index_nestloop off)*/ (若加在最外层,可以使用global;否则需要去掉global,不然hint无法生效)
设置全局参数 set enable_index_nestloop = off; (先执行该语句,再执行原始SQL

image.png
从上图中可以看出,走全表扫描+Hash Join的效率远远优于 Index Scan+Nest Loop,SQL语句3s+就执行完毕。

不等值关联

由于Hash Join仅支持等值关联的情况,因此若SQL语句中存在不等值关联,则优化器只会执行Nest Loop算子,不等值关联有多种情况,本文先介绍去HANA优化过程中遇到的两种:

(1)or不等值关联改写

image.png
从上图中可以看出,该语句执行过程中的性能瓶颈在于Nest Loop算子,利用hint或全局参数无法避免,因为SQL语句中存在or不等值关联

SELECT
    t2.PARTNER_CHANNEL_CODE   AS CHANNEL_ID
    ,t1.COUNTRY_CODE
    ,t1.BRAND
    ,t2.CHANNEL_ID            AS CHANNEL_ID2
FROM  PRIMARY_KEY_BEFOR t1
LEFT JOIN
(
    SELECT
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE  AS  CHANNEL_ID
    FROM   BI_DASHBOARD.RPT_PSI_CHANNEL_CUSTOMER_D T
    GROUP BY
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE
)t2
ON  (t2.CHANNEL_ID           =  t1.CHANNEL_ID  AND  t1.TYPE='DR')
OR  (t2.PARTNER_CHANNEL_CODE =  t1.CHANNEL_ID  AND  t1.TYPE='ALL' )
GROUP BY t2.PARTNER_CHANNEL_CODE
        ,t1.COUNTRY_CODE
        ,t1.BRAND
        ,t2.CHANNEL_ID

利用 UNION ALL(如果要求结果集去重的话使用 UNION),修改后SQL如下所示:

SELECT
    t2.PARTNER_CHANNEL_CODE   AS CHANNEL_ID
    ,t1.COUNTRY_CODE
    ,t1.BRAND
    ,t2.CHANNEL_ID            AS CHANNEL_ID2
FROM  PRIMARY_KEY_BEFOR t1
LEFT JOIN
(
    SELECT
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE  AS  CHANNEL_ID
    FROM   BI_DASHBOARD.RPT_PSI_CHANNEL_CUSTOMER_D T
    GROUP BY
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE
)t2
ON  (t2.CHANNEL_ID           =  t1.CHANNEL_ID  AND  t1.TYPE='DR')
GROUP BY t2.PARTNER_CHANNEL_CODE
        ,t1.COUNTRY_CODE
        ,t1.BRAND
        ,t2.CHANNEL_ID
UNION
SELECT
    t2.PARTNER_CHANNEL_CODE   AS CHANNEL_ID
    ,t1.COUNTRY_CODE
    ,t1.BRAND
    ,t2.CHANNEL_ID            AS CHANNEL_ID2
FROM  PRIMARY_KEY_BEFOR t1
LEFT JOIN
(
    SELECT
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE  AS  CHANNEL_ID
    FROM   BI_DASHBOARD.RPT_PSI_CHANNEL_CUSTOMER_D T
    GROUP BY
    PARTNER_CHANNEL_CODE
    ,CUST_ACCOUNT_NUM||'/'||CHANNEL_MODE_CODE
)t2
ON  (t2.PARTNER_CHANNEL_CODE =  t1.CHANNEL_ID  AND  t1.TYPE='ALL' )
GROUP BY t2.PARTNER_CHANNEL_CODE
        ,t1.COUNTRY_CODE
        ,t1.BRAND
        ,t2.CHANNEL_ID

UNION (ALL)补充

  • union:
    UNION用于合并多个查询结果,并且会自动去除重复的行,确保最终的结果集中没有重复数据。这种去重操作的好处是我们可以获得干净、唯一的结果集,但同时也带来了性能开销。去重操作需要比较和过滤结果集中的每一行,这可能会导致较大的性能消耗。因此,在使用UNION操作符时,需要权衡结果集的唯一性和性能开销之间的折衷。
  • union all:
    UNION ALL也用于合并多个查询结果,但是,它不进行去重操作。这意味着UNION ALL返回的结果集可能包含重复的行。然而,由于没有去重的开销,UNION ALL的性能通常比UNION更好。如果我们已经确保结果集中没有重复行,或者我们不关心结果集中的重复行,那么使用UNION ALL可以获得更好的查询性能。
  • 两者区别
    结果集:UNION会在结果集中去重
    结果集顺序:UNION会在最终结果集进行排序,UNION ALL不会进行排序,结果集顺序由各个子查询顺序决定
    性能:由于UNION会去重和排序,因此UNION ALL的性能要优于UNION。

image.png
从整改后的SQL执行计划中可以看出来,去掉Nest Loop算子后,SQL执行时间降为500ms左右,大大优化了语句执行性能

(2) between不等值关联改写

image.png
该SQL的性能瓶颈同样在于Nest Loop算子,查看其原始SQL语句

SELECT 
    'W' AS DIMENSION,
	ECODE('W','W',LEFT(TO_CHAR(P.PERIOD_ID),4)||'WK' || LPAD(P.WEEK_NO, 2, '0')||date_format(P. PERIOD_ST_DATE, '%Y%m%d'),'M',LEFT(TO_CHAR(P.PERIOD_ID),4)||date_format(ADDDATE(P.PERIOD_ST_DATE,3),'%m'),'Q',LEFT(date_format(QD.PERIOD_ST_DATE,'%Y%m%d'),4)||'Q' || quarter(QD.PERIOD_ST_DATE),'Y',LEFT(TO_CHAR(P.PERIOD_ID),4)) AS "TIME",
	SUM(AATP) AS AATP,                  -- AATP
	SUM(FCST_QTY) AS FCST_QTY,              -- 要货预测
	SUM(SHIPPED_QTY) AS SHIPPED_QTY,        -- 已发货
	SUM(SALES_RPD_QTY) AS SALES_RPD_QTY,   -- 代表处DFS SO RPD数量
	SUM(SALES_EPD_QTY) AS SALES_EPD_QTY,   -- 代表处DFS SO EPD数量
	SUM(PRESO_RPD_QTY) AS PRESO_RPD_QTY,-- RPD(PreSO)
	SUM(PRESO_EPD_QTY) AS PRESO_EPD_QTY,-- EPD(PreSO)
	SUM(NET_RPD_QTY) AS NET_RPD_QTY,      
	SUM(NET_EPD_QTY) AS NET_EPD_QTY,
	SUM(CURRENT_TIME_LEFT_AATP) AS CURRENT_TIME_LEFT_AATP,        -- 当周剩余AATP:AATP-已发货-DFS SO EPD
	SUM(EPD_MORE_QTY) AS EPD_MORE_QTY

FROM (SELECT PD.PERIOD_ID,PD.PERIOD_ST_DATE,PD.WEEK_NO,PD.PERIOD_END_DATE FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='D' AND PD.DEL_FLAG = 'N') D
LEFT JOIN (......) 
    ON D.PERIOD_ID  = CAST(date_format(DFS_DATE,'%Y%m%d') as bigint)
LEFT JOIN (SELECT PD.PERIOD_ID,PD.PERIOD_ST_DATE,PD.WEEK_NO,PD.PERIOD_END_DATE FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='W' AND PD.DEL_FLAG = 'N') P
	ON D.PERIOD_ID BETWEEN CAST(date_format(P.PERIOD_ST_DATE,'%Y%m%d') as bigint) AND CAST(date_format(P.PERIOD_END_DATE,'%Y%m%d') as bigint)
LEFT JOIN (SELECT PD.PERIOD_ST_DATE,PD.PERIOD_END_DATE FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='Q' AND PD.DEL_FLAG = 'N') QD
	ON D.PERIOD_ID BETWEEN CAST(date_format(QD.PERIOD_ST_DATE,'%Y%m%d') as bigint)AND CAST(date_format(QD.PERIOD_END_DATE,'%Y%m%d') as bigint)

WHERE D.PERIOD_ID BETWEEN CAST(date_format('2023-01-01','%Y%m%d') as bigint) AND CAST(date_format('2023-08-01','%Y%m%d') as bigint)

GROUP BY 1,2

原始SQL语句中,存在between非等值关联,因此,从between中的值入手进行分析,该语句语义是,从DMISC.DM_DIM_CBG_PERIOD_D表中取出PERIOD_TYPE = ‘D’(Day),然后跟从该表取出的PERIOD_TYPE = ‘W’(Week)进行关联,最后和从该表取出的PERIOD_TYPE = ‘Q’(Quarter)进行关联,原始SQL是利用between字段中的开始日期与结束日期进行关联。查看该表中的所有字段,发现可以换一种思路,PERIOD_TYPE = 'D’情况下有非空字段year、qtr_no(季度)、month_no、week_no(周)PERIOD_TYPE = 'W’情况下有非空字段year、week_no(周)PERIOD_TYPE = 'Q’情况下有非空字段year、qtr_no(季度),此时可以利用year、week_no/qtr_no来进行关联。
优化后的SQL如下所示:


FROM (SELECT PD.YEAR,PD.PERIOD_ID,PD.PERIOD_ST_DATE,PD.WEEK_NO,PD.PERIOD_END_DATE FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='D' AND PD.DEL_FLAG = 'N') D
LEFT JOIN (......)  
ON D.PERIOD_ID  = CAST(date_format(DFS_DATE,'%Y%m%d') as bigint)

LEFT JOIN (SELECT * FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='W' AND PD.DEL_FLAG = 'N') P ON D.year = P.year and D.week_no = P.week_no

LEFT JOIN (SELECT * FROM DMISC.DM_DIM_CBG_PERIOD_D PD WHERE PD.PERIOD_TYPE='Q' AND PD.DEL_FLAG = 'N') QD ON D.year = QD.year and D.week_no = QD.qtr_no

WHERE D.PERIOD_ID BETWEEN CAST(date_format('2023-01-01','%Y%m%d') as bigint) AND CAST(date_format('2023-08-01','%Y%m%d') as bigint)
GROUP BY 1,2

image.png
从上图优化后的SQL执行计划中可以看到,耗时降低为900ms+

小结

DWS中通常会避免使用Nest Loop算子,除非出现毫无关联条件的情况(不常出现),遇到Nest Loop算子时先采用hint或全局参数进行规避,如果未生效,则证明SQL语句存在非等值关联,要对SQL语句的关联逻辑进行整改

4、避免关联发散引起的性能瓶颈

业务问题

如下图所示,SQL语句执行过程中,存在关联发散导致结果集数量过大,同时,要对这么大体量的数据进行排序去重,两者效果叠加,语句执行时间达到了65s+。
image.png
存在数据发散的SQL语句如下所示

SELECT D.LV1_PROD_LIST_EN_NAME                                                            AS LV1_RPOD_EN_NAME,
         F.EXTERNAL_NAME                                                                    AS EXTERNAL_NAME,
         D.LV1_PROD_LIST_CODE                                                               AS LV1_PROD_LIST_CODE,
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY ELSE NULL END)           AS SO_QTY_ACT1,
         SUM(CASE WHEN F.PERIOD_ID=20230509 THEN F.SO_QTY ELSE NULL END)          AS SO_QTY_ACT2,
         SUM(CASE WHEN F.PERIOD_ID=20230508 THEN F.SO_QTY ELSE NULL END)          AS SO_QTY_ACT3,
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_LAST ELSE NULL END)      AS SO_QTY_LAST,
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_WTD ELSE NULL END)       AS SO_QTY_WTD1,
         SUM(CASE WHEN F.PERIOD_ID=20230507 THEN F.SO_QTY_WTD ELSE NULL END)      AS SO_QTY_WTD2,  
         SUM(CASE WHEN F.PERIOD_ID=20230430 THEN F.SO_QTY_WTD ELSE NULL END)      AS SO_QTY_WTD3,
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_WTD_LAST ELSE NULL END)  AS SO_QTY_WTD_LAST, 
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_MTD ELSE NULL END)       AS SO_QTY_MTD1, 
         SUM(CASE WHEN F.PERIOD_ID=20230430 THEN F.SO_QTY_MTD ELSE NULL END)      AS SO_QTY_MTD2,
         SUM(CASE WHEN F.PERIOD_ID=20230331 THEN F.SO_QTY_MTD ELSE NULL END)      AS SO_QTY_MTD3,
         SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_MTD_LAST ELSE NULL END)  AS SO_QTY_MTD_LAST         
    FROM BI_DASHBOARD.DM_MSS_OS_PC_AREA_SO_COL_D_F F
    INNER JOIN BI_DASHBOARD.DM_MSS_ITEM_PRODUCT_D D ON F.EXTERNAL_NAME = D.MKT_NAME AND D.LV1_PROD_LIST_FLAG = 'MH'
    WHERE 1=1
    AND F.PERIOD_ID IN (20230510,20230509,20230508,20230507,20230430,20230430,20230331)
    AND F.EXTERNAL_NAME IN ( SELECT MKT_NAME EXTERNAL_NAME  
		       FROM BI_DASHBOARD.DM_MSS_ITEM_PRODUCT_D PRD
		      WHERE PRD.COMPANY_BRAND =any(array[string_to_array('HUAWEI,HONER',',')])
		            AND MKT_NAME<>'SNULL' GROUP BY MKT_NAME)
    AND (F.LARGE_AREA_CODE IN  ('') OR '' IS NULL OR ''= '')
    AND (F.SMALL_AREA_CODE IN  ('') OR '' IS NULL OR ''= '')
     AND F.ECOSYSTEM = 'AG'  
     AND F.SALES_FLAG = '1' 
     AND F.ORG_CODE=F.SIGN_COUNTRY_PROVINCE_CODE 
    GROUP BY F.EXTERNAL_NAME,D.LV1_PROD_LIST_EN_NAME,D.LV1_PROD_LIST_CODE

分析思路

image.png
从图中标记的地方可以看出,SQL在执行过程中,F表与D表关联时存在严重的数据发散现象,同时,sort排序处处理大数据量的结果集也导致执行时间过长。
对原始SQL进行分析,该SQL语义是:对F表进行过滤,然后与D表进行关联,取某几个固定年份的数据求和,查询最后输出的f表的值仅为EXTERNAL_NAME 并且关联条件也是EXTERNAL_NAME,此时,可以针对该SQL进行改写,可以先对f表的EXTERNAL_NAME值进行去重再关联,从而降低窗口函数中排序时的数据量,以提高语句执行效率。
改写后的SQL如下所示:

SELECT D.LV1_PROD_LIST_EN_NAME                                                            AS LV1_RPOD_EN_NAME,
         F.EXTERNAL_NAME                                                                    AS EXTERNAL_NAME,
         D.LV1_PROD_LIST_CODE                                                               AS LV1_PROD_LIST_CODE,
         SUM(F.SO_QTY_ACT1)           AS SO_QTY_ACT1,
         SUM(F.SO_QTY_ACT2)          AS SO_QTY_ACT2,
         SUM(F.SO_QTY_ACT3)          AS SO_QTY_ACT3,
         SUM(F.SO_QTY_LAST)      AS SO_QTY_LAST,
         SUM(F.SO_QTY_WTD1)       AS SO_QTY_WTD1,
         SUM(F.SO_QTY_WTD2)      AS SO_QTY_WTD2,  
         SUM(F.SO_QTY_WTD3)      AS SO_QTY_WTD3,
         SUM(F.SO_QTY_WTD_LAST)  AS SO_QTY_WTD_LAST, 
         SUM(F.SO_QTY_MTD1)       AS SO_QTY_MTD1, 
         SUM(F.SO_QTY_MTD2)      AS SO_QTY_MTD2,
         SUM(F.SO_QTY_MTD3)      AS SO_QTY_MTD3,
         SUM(F.SO_QTY_MTD_LAST)  AS SO_QTY_MTD_LAST         
    FROM (
	 select EXTERNAL_NAME,
		SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY ELSE NULL END)           AS SO_QTY_ACT1,
         	SUM(CASE WHEN F.PERIOD_ID=20230509 THEN F.SO_QTY ELSE NULL END)          AS SO_QTY_ACT2,
         	SUM(CASE WHEN F.PERIOD_ID=20230508 THEN F.SO_QTY ELSE NULL END)          AS SO_QTY_ACT3,
         	SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_LAST ELSE NULL END)      AS SO_QTY_LAST,
         	SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_WTD ELSE NULL END)       AS SO_QTY_WTD1,
         	SUM(CASE WHEN F.PERIOD_ID=20230507 THEN F.SO_QTY_WTD ELSE NULL END)      AS SO_QTY_WTD2,  
         	SUM(CASE WHEN F.PERIOD_ID=20230430 THEN F.SO_QTY_WTD ELSE NULL END)      AS SO_QTY_WTD3,
         	SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_WTD_LAST ELSE NULL END)  AS SO_QTY_WTD_LAST, 
         	SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_MTD ELSE NULL END)       AS SO_QTY_MTD1, 
         	SUM(CASE WHEN F.PERIOD_ID=20230430 THEN F.SO_QTY_MTD ELSE NULL END)      AS SO_QTY_MTD2,
         	SUM(CASE WHEN F.PERIOD_ID=20230331 THEN F.SO_QTY_MTD ELSE NULL END)      AS SO_QTY_MTD3,
         	SUM(CASE WHEN F.PERIOD_ID=20230510 THEN F.SO_QTY_MTD_LAST ELSE NULL END)  AS SO_QTY_MTD_LAST   
	 from BI_DASHBOARD.DM_MSS_OS_PC_AREA_SO_COL_D_F F 
	 WHERE F.PERIOD_ID IN (20230510,20230509,20230508,20230507,20230430,20230430,20230331)
   	 AND F.EXTERNAL_NAME IN ( SELECT MKT_NAME EXTERNAL_NAME 
				  FROM BI_DASHBOARD.DM_MSS_ITEM_PRODUCT_D PRD
		      		  WHERE PRD.COMPANY_BRAND =any(array[string_to_array('HUAWEI,HONER',',')])
	 AND MKT_NAME<>'SNULL' GROUP BY MKT_NAME)
    	 AND (F.LARGE_AREA_CODE IN  ('') OR '' IS NULL OR ''= '')
    	 AND (F.SMALL_AREA_CODE IN  ('') OR '' IS NULL OR ''= '')
    	 AND F.ORG_CODE=F.SIGN_COUNTRY_PROVINCE_CODE 
 	 AND F.ECOSYSTEM = 'AG'  
     	 AND F.SALES_FLAG = '1' 
	 group by EXTERNAL_NAME)F
    INNER JOIN BI_DASHBOARD.DM_MSS_ITEM_PRODUCT_D D ON F.EXTERNAL_NAME = D.MKT_NAME AND D.LV1_PROD_LIST_FLAG = 'MH'
    WHERE 1=1
    GROUP BY F.EXTERNAL_NAME,D.LV1_PROD_LIST_EN_NAME,D.LV1_PROD_LIST_CODE

在改写的SQL中,先对f表进行去重,然后再让其与d表进行关联,其执行计划如下图所示:
image.png

小结

关联前去重操作需要考虑使用场景,如果后续关联或者输出结果涉及到很多该表的字段,那么对该表做提前去重操作可能会起到相反的效果,影响语句执行性能,甚至影响结果集的准确性。因此,提前去重更适用于后续操作涉及到的字段不多,且提前去重不影响结果集的场景 (需要自己动手尝试一下)

5、总结

上述四个部分是梳理出来的较为常见的关联慢优化思路,像关联倾斜优化的解决办法是适用于大部分场景(只要识别出来存在关联时数据倾斜)调整关联顺序,不等值改等值关联、关联前去重这三种方法需要结合问题SQL具体考虑,不能直接使用。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。