发布网友 发布时间:21小时前
共1个回答
热心网友 时间:20小时前
本文分享自华为云社区《 GaussDB(DWS)性能调优:row_number() over(p)-rn=1性能瓶颈发现和改写套路》,作者:Zawami 。
本套路应用于子查询中含有row_number() over(partition by order by) rn,并仅把rn列用于分类排序后筛选最大值的场景。
GaussDB中SQL语句的执行很多时候是流式的,即对每一条数据进行流水加工,各层算子同时在执行,缩短执行耗时。
然而,在特定情况下,SQL需要先获取前一个算子的全部结果集,才能继续下一步处理。窗口函数是导致这种延迟的常见原因。
在观察执行计划时,我们发现SQL在计算rn列后,需进行与本层其他列的关联。由于存在窗口函数,SQL必须等待51号算子执行完毕,才能进行关联,这造成了性能瓶颈。
通过移除窗口函数,我们可以实现分类汇总与明细数据之间的流水执行。
改写前局部SQL:
改写后局部SQL:
改写解析:首先,我们根据原SQL中row_number() over()的partition列和order列进行数据去重。由于原SQL未定义LIFE_CYCLE的排序方式,改写时我们既可以使用MAX也可以使用MIN函数进行聚合。之后,我们对去重后的数据进行筛选。
使用此修改方法,对比了修改前后的全量执行计划,并在附件中提供。
这种改写方法解决了上层算子等待窗口函数的问题。发现对于不涉及聚合的其他列,如例子中的LIFE_CYCLE,若还需进一步聚合,则本层子查询中的去重并非必要。可进一步去除这层去重。
改写后执行计划如下:
可见,尽管51层算子的执行时间仅缩短了200ms,但减少了阻塞,导致1~7层算子的执行时间大幅缩短,总体执行时间比原先快了约480ms。