case1828.md
February 21, 2020 · View on GitHub
现象
执行 union select 聚合查询出现 OOM 。
环境信息收集
版本
v2.1.0-rc.3-5-g99c4a15
部署情况
- SQL 与 执行计划、表结构详见 test.sql
分析步骤
- 抓取火焰图,获取内存使用情况。
- 重新收集相关表的统计信息,发现依然会发生 OOM 的情况。
- sql 是一个 union 连接了两个 hashagg,然后再对这个 union 执行 hashagg 。 OOM 可能发生在 union 并行执行的时候,也可能发生在最外面的 hashagg 。所以先在 union 外面加了个 order by,把最外面的 agg 改成 streamagg 试一下,看会不会 OOM 。修改 SQL 如下,再进行测试。结果还是出现 OOM 。
SELECT tmp_amt.channel_id channel_id, tmp_amt.sub_channel sub_channel, tmp_amt.activity_info activity_info,tmp_amt.product_code product_code,
0 uv_num, 0 register_num, 0 complete_num_newu, 0 complete_num_oldu, 0 aps_num_newu, 0 aps_amt_newu, 0 aps_num_newu, 0 aps_amt_newu, 0 draw_num_newu, 0 draw_num_oldu,
0 loan_num_newu, 0 loan_num_oldu, 0 loan_amt_newu, 0 loan_amt_oldu, 0 loan_num_sj, 0 loan_amt_sj, 0 loan_num_fj, 0 loan_amt_fj,
SUM(tmp_amt.accu_loan_amt) accu_loan_amt, SUM(tmp_amt.acct_repay_amt) acct_repay_amt,
0 loan_user_sj,0 loan_amt_sj_xxx,0 loan_user_newu,0 loan_user_oldu,0 first_complete_num_newu, 0 first_complete_num_oldu FROM
(
SELECT *
(
select uu.channel_id channel_id, coalesce(uu.sub_channel, '') sub_channel, coalesce(uu.activity_info, '') activity_info,
case when aae.appl_no is not null and aa.product_code in ('JT', 'JX', 'MA') then aa.product_code||'_BJ' else aa.product_code end as product_code,
0 accu_loan_amt, sum(COALESCE(flow.trans_prin, 0)) AS acct_repay_amt
from u_user uu
join (select aa.user_no, aa.appl_no, aa.contract_no, aa.product_code from ap_appl aa where aa.appl_state='APS' and aa.contract_no is not null
AND aa.product_code in ('JT', 'YJ', 'JX', 'MA') group by aa.user_no, aa.appl_no, aa.contract_no, aa.product_code) aa on uu.user_no = aa.user_no
join tran_proc_rp flow on aa.contract_no = flow.contract_no
join ln_loan loan on flow.loan_no = loan.loan_no
left join ap_appl_ext aae on aa.appl_no = aae.appl_no and aae.credit_ident='Y'
where flow.date_rp < '2018-10-11 00:00:00' AND flow.status = '03'
GROUP BY uu.channel_id, coalesce(uu.sub_channel, ''), coalesce(uu.activity_info, ''),
case when aae.appl_no is not null and aa.product_code in ('JT', 'JX', 'MA') then aa.product_code||'_BJ' else aa.product_code end
UNION ALL
select uu.channel_id channel_id, coalesce(uu.sub_channel, '') sub_channel, coalesce(uu.activity_info, '') activity_info,
case when aae.appl_no is not null and aa.product_code in ('JT', 'JX', 'MA') then aa.product_code||'_BJ' else aa.product_code end as product_code,
sum(COALESCE(loan.loan_amt, 0)) AS accu_loan_amt,0 acct_repay_amt
from u_user uu
join (select aa.user_no, aa.appl_no, aa.contract_no, aa.product_code from ap_appl aa where aa.appl_state='APS' and aa.contract_no is not null
AND aa.product_code in ('JT', 'YJ', 'JX', 'MA') group by aa.user_no, aa.appl_no, aa.contract_no, aa.product_code) aa on uu.user_no = aa.user_no
join ln_loan loan on aa.contract_no = loan.contract_no
left join ap_appl_ext aae on aa.appl_no = aae.appl_no and aae.credit_ident='Y'
where loan.date_created < '2018-10-11 00:00:00'
GROUP BY uu.channel_id, coalesce(uu.sub_channel, ''), coalesce(uu.activity_info, ''),
case when aae.appl_no is not null and aa.product_code in ('JT', 'JX', 'MA') then aa.product_code||'_BJ' else aa.product_code end
) tmp_amt
order by tmp_amt.channel_id, tmp_amt.sub_channel, tmp_amt.activity_info, tmp_amt.product_code ) tmp_amt --在 union 外面套了层 order by,走 stream agg
GROUP BY tmp_amt.channel_id, tmp_amt.sub_channel, tmp_amt.activity_info, tmp_amt.product_code
- 把最外层的 agg 去掉,直接 select * from( union all), 仍会出现 OOM 的问题。
- 单独执行 union all 里面的每一个 select 并不会引起 OOM 。
结论
Union 并行执行 select 引起的 OOM 问题。