为何GROUP BY查询可利用索引,而SUM窗口函数查询无法使用索引?
性能差异原因解析
查询1b(GROUP BY方案)快的核心原因
数据库优化器支持谓词下推,你外层的where wonum = 'WO360996'里的wonum是子查询中wogroup的别名,优化器可以直接将过滤条件下沉到内层的GROUP BY逻辑之前,执行顺序变成:
- 先走
WORKORDER_NDX32索引范围扫描,定位所有wogroup = 'WO360996'的行(也就是目标工单和它的所有子任务,一般只有寥寥几行) - 对这少量行直接做分组聚合,因为索引本身是有序的,分组不需要额外排序(执行计划里的
SORT GROUP BY NOSORT就是这个意思)
整个过程只扫描了个位数的行,自然只需要几十毫秒。
查询2(窗口函数方案)慢的核心原因
窗口函数的逻辑优先级高于外层过滤,且优化器无法做谓词下推:
- 你定义的窗口函数是
partition by wogroup,需要对每个wogroup分区的所有行计算SUM值,而你外层的过滤条件是针对wonum字段的,wonum和wogroup不是同一个字段,优化器无法推断出你只需要wogroup = 'WO360996'这个分区的计算结果 - 所以执行时只能先全表扫描所有35万行WORKORDER数据,给所有行都计算完窗口函数的SUM结果,最后才过滤出你要的那一行
等于白白计算了35万行的聚合值,耗时自然飙升到秒级。
窗口函数的优化思路
如果要让窗口函数版本也走索引,可以主动把wogroup的过滤条件加到最内层:
select * from ( select wonum, actlabcost_tasks_incl, actmatcost_tasks_incl, acttoolcost_tasks_incl, actservcost_tasks_incl, acttotalcost_tasks_incl, other_wo_columns from ( select wonum, istask, sum(actlabcost ) over (partition by wogroup) as actlabcost_tasks_incl, sum(actmatcost ) over (partition by wogroup) as actmatcost_tasks_incl, sum(acttoolcost) over (partition by wogroup) as acttoolcost_tasks_incl, sum(actservcost) over (partition by wogroup) as actservcost_tasks_incl, sum(actlabcost + actmatcost + acttoolcost + actservcost) over (partition by wogroup) as acttotalcost_tasks_incl, rowstamp as other_wo_columns from maximo.workorder -- 主动加wogroup过滤,引导优化器走索引 where wogroup = (select wogroup from maximo.workorder where wonum = 'WO360996') ) where istask = 0 ) where wonum in ('WO360996')
修改后也能走WORKORDER_NDX32索引,性能和GROUP BY版本基本一致。
内容的提问来源于stack exchange,提问作者User1974
相关产品推荐
相关产品推荐

