本文分享自華為雲社區《GaussDB(DWS)性能調優:Sort+Groupagg聚集引起的性能瓶頸案例》,作者: O泡果奶~ 。 本文針對SQL語句長時間執行不出來,且verbose執行計劃中出現Sort+GroupAgg聚集方式的案例進行分析。 1、【問題描述】 語句執行時間過長,2300s+也 ...
本文分享自華為雲社區《GaussDB(DWS)性能調優:Sort+Groupagg聚集引起的性能瓶頸案例》,作者: O泡果奶~ 。
本文針對SQL語句長時間執行不出來,且verbose執行計劃中出現Sort+GroupAgg聚集方式的案例進行分析。
1、【問題描述】
語句執行時間過長,2300s+也無法得出結果。從verbose執行計劃可以看出存在sort聚合。
2、【原始語句】
SELECT /*+ set global(agg_redistribute_enhancement on) set global (best_agg_plan 3)*/ dm_ebg_glb_kpi_sum_w_v."na_level_name", dm_ebg_glb_kpi_sum_w_v."na_level", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_code", dm_ebg_glb_kpi_sum_w_v."period_id", dm_ebg_glb_kpi_sum_w_v."year", dm_ebg_glb_kpi_sum_w_v."month", dm_ebg_glb_kpi_sum_w_v."report_category_cn_name", dm_ebg_glb_kpi_sum_w_v."report_category_en_name", dm_ebg_glb_kpi_sum_w_v."currency_code", dm_ebg_glb_kpi_sum_w_v."exchange_rate_type_cn_name", dm_ebg_glb_kpi_sum_w_v."exchange_rate_type_en_name", dm_ebg_glb_kpi_sum_w_v."report_item_code", dm_ebg_glb_kpi_sum_w_v."report_item_cn_name", dm_ebg_glb_kpi_sum_w_v."report_item_en_name", dm_ebg_glb_kpi_sum_w_v."report_item_type", dm_ebg_glb_kpi_sum_w_v."report_item_flag", dm_ebg_glb_kpi_sum_w_v."region_code", dm_ebg_glb_kpi_sum_w_v."region_cn_name", dm_ebg_glb_kpi_sum_w_v."region_en_name", dm_ebg_glb_kpi_sum_w_v."oversea_flag", dm_ebg_glb_kpi_sum_w_v."repoffice_code", dm_ebg_glb_kpi_sum_w_v."repoffice_cn_name", dm_ebg_glb_kpi_sum_w_v."repoffice_en_name", dm_ebg_glb_kpi_sum_w_v."ebg_focus_cn_name", dm_ebg_glb_kpi_sum_w_v."ebg_focus_en_name", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."named_account_flag", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_code", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_cn_name", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_en_name", dm_ebg_glb_kpi_sum_w_v."industry_class_code", dm_ebg_glb_kpi_sum_w_v."industry_class_cn_name", dm_ebg_glb_kpi_sum_w_v."industry_class_en_name", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_code", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_cn_name", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_en_name", dm_ebg_glb_kpi_sum_w_v."focus_industry_cn_name", dm_ebg_glb_kpi_sum_w_v."focus_industry_en_name", dm_ebg_glb_kpi_sum_w_v."sales_mode_code", dm_ebg_glb_kpi_sum_w_v."sales_mode_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_mode_en_name", SUM(dm_ebg_glb_kpi_sum_w_v."ptd_amt") as "ptd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."py_ptd_amt") as "py_ptd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."pp_ptd_amt") as "pp_ptd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."qtd_amt") as "qtd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."py_qtd_amt") as "py_qtd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."pp_qtd_amt") as "pp_qtd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."ytd_amt") as "ytd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."py_ytd_amt") as "py_ytd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."py_all_ytd_amt") as "py_all_ytd_amt", SUM(dm_ebg_glb_kpi_sum_w_v."end_bal_amt") as "end_bal_amt", SUM(dm_ebg_glb_kpi_sum_w_v."cp_open_bal_amt") as "cp_open_bal_amt", SUM(dm_ebg_glb_kpi_sum_w_v."pq_end_bal_amt") as "pq_end_bal_amt", SUM(dm_ebg_glb_kpi_sum_w_v."cy_open_bal_amt") as "cy_open_bal_amt", SUM(dm_ebg_glb_kpi_sum_w_v."py_end_bal_amt") as "py_end_bal_amt" FROM fin_dmr_ebgdis.dm_ebg_glb_kpi_sum_w_v where 1 = 1 and 1 = 1 AND dm_ebg_glb_kpi_sum_w_v."period_id" = 202302 group by dm_ebg_glb_kpi_sum_w_v."na_level_name", dm_ebg_glb_kpi_sum_w_v."na_level", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv1_prod_list_code", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv3_prod_list_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_lv0_prod_list_en_name", dm_ebg_glb_kpi_sum_w_v."sales_lv2_prod_list_code", dm_ebg_glb_kpi_sum_w_v."period_id", dm_ebg_glb_kpi_sum_w_v."year", dm_ebg_glb_kpi_sum_w_v."month", dm_ebg_glb_kpi_sum_w_v."report_category_cn_name", dm_ebg_glb_kpi_sum_w_v."report_category_en_name", dm_ebg_glb_kpi_sum_w_v."currency_code", dm_ebg_glb_kpi_sum_w_v."exchange_rate_type_cn_name", dm_ebg_glb_kpi_sum_w_v."exchange_rate_type_en_name", dm_ebg_glb_kpi_sum_w_v."report_item_code", dm_ebg_glb_kpi_sum_w_v."report_item_cn_name", dm_ebg_glb_kpi_sum_w_v."report_item_en_name", dm_ebg_glb_kpi_sum_w_v."report_item_type", dm_ebg_glb_kpi_sum_w_v."report_item_flag", dm_ebg_glb_kpi_sum_w_v."region_code", dm_ebg_glb_kpi_sum_w_v."region_cn_name", dm_ebg_glb_kpi_sum_w_v."region_en_name", dm_ebg_glb_kpi_sum_w_v."oversea_flag", dm_ebg_glb_kpi_sum_w_v."repoffice_code", dm_ebg_glb_kpi_sum_w_v."repoffice_cn_name", dm_ebg_glb_kpi_sum_w_v."repoffice_en_name", dm_ebg_glb_kpi_sum_w_v."ebg_focus_cn_name", dm_ebg_glb_kpi_sum_w_v."ebg_focus_en_name", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv0_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv1_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv2_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rnd_team_code", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rd_team_cn_name", dm_ebg_glb_kpi_sum_w_v."lv3_prod_rd_team_en_name", dm_ebg_glb_kpi_sum_w_v."named_account_flag", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_code", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_cn_name", dm_ebg_glb_kpi_sum_w_v."domtc_entps_indu_class_en_name", dm_ebg_glb_kpi_sum_w_v."industry_class_code", dm_ebg_glb_kpi_sum_w_v."industry_class_cn_name", dm_ebg_glb_kpi_sum_w_v."industry_class_en_name", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_code", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_cn_name", dm_ebg_glb_kpi_sum_w_v."sub_industry_class_en_name", dm_ebg_glb_kpi_sum_w_v."focus_industry_cn_name", dm_ebg_glb_kpi_sum_w_v."focus_industry_en_name", dm_ebg_glb_kpi_sum_w_v."sales_mode_code", dm_ebg_glb_kpi_sum_w_v."sales_mode_cn_name", dm_ebg_glb_kpi_sum_w_v."sales_mode_en_name" limit 200
3、【性能分析】
由於語句長時間無法執行完畢,通過其verbose執行計劃中的E-rows可以看出,由於較小且去重後行數變化不大,優化器採用了Sort+GroupAgg的聚集方式。
通常情況下,Sort+GroupAgg性能並不如Hashagg,此時,可以通過利用
set enable_sort = off;
或是
+set [gloabal] (enable_sort off)
來避免使用Sort+GroupAgg聚集方式。
補充:Sort+GroupAgg與Hashagg對比
Hashagg |
Sort+GroupAgg | |
---|---|---|
執行方式 |
每行元組根據聚集列散列建立hash表,進行去重比較 |
所有元組排序後進行聚集去重操作 |
限制 |
所有聚集列支持hash散列 |
所有聚集列支持排序 |
優勢 |
通過哈希散列比較可以快速定位到重覆元組 |
輸出結果保持有序,有利於後續有序操作 |
劣勢 |
受初始散列桶個數影響較大 |
如果初始集較大,Sort性能較差 |
適合使用的情況 |
去重後行數較少的場景 |
相比Hashagg,當去重後行數和輸入行數差不多,且輸入行數較少時適用 |
從上圖中可以看出,調優後語句執行時間下降為22s+,性能大大提高。從performance計劃可以看出,原始SQL語句verbose計劃中E-rows不准確,導致優化器選擇了Sort+GroupAgg聚集方式,從而使得語句執行性能下降。
附件enable_sort-1為調優前verbose執行計劃,附件enable_sort-2為調優後performance執行計劃
- 附件:enable_sort-1.txt688.04KB
- 附件:enable_sort-2.txt1.57MB