如何利用大量聚合优化查询

时间:2011-07-19 18:47:32

标签: sql db2 query-optimization

如何优化此查询?现在,它的运行速度太慢了~10秒。以下详细信息:

SELECT ProjectName, 
       Actuals_YTD, 
       Rem_Forecast, 
       Total_Forecast, 
       Approved_Budget, 
       Variance, 
       Variance_Percentage, 
       ProjectComments, 
       VersionType, 
       ModifiedDate 
FROM (SELECT pd.ProjectId, 
             pd.ProjectName, 
             SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) <= '06/01/2011' THEN feb.USDactualamount ELSE 0.0 END) AS Actuals_YTD, 
             SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) > '06/01/2011' THEN feb.forecastusd ELSE 0.0 END) AS Rem_Forecast, 
             ((SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) <= '06/01/2011' THEN feb.USDactualamount ELSE 0.0 END)) + (SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) > '06/01/2011' then feb.forecastusd else 0.0 end))) AS Total_Forecast, 
             SUM(COALESCE((feb.REVISEDPLANUSD),0)) AS Approved_Budget, 
             ((SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) <= '06/01/2011' THEN feb.USDactualamount ELSE 0.0 END)) + (SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) > '06/01/2011' then feb.forecastusd else 0.0 end))) - ((SUM(COALESCE((feb.REVISEDPLANUSD),0)))) AS Variance, 
             CASE WHEN (SUM(COALESCE((feb.REVISEDPLANUSD),0))) = 0 THEN NULL ELSE ((((((SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(base.ProjectMonth) <= '06/01/2011' THEN feb.USDactualamount else 0.0 end)) + (SUM(CASE WHEN RPD.PROJECTMONTH_TO_DATE(projectmonth) > '06/01/2011' then feb.forecastusd else 0.0 end)))) - (SUM(COALESCE((feb.REVISEDPLANUSD),0)))) / (SUM(COALESCE((feb.REVISEDPLANUSD),0)))) * 100) END AS Variance_Percentage, 
             pd.ProjectAux1, 
             pd.ProjectComments, 
             pd.VersionType, 
             MAX(base.ModifiedDate) AS ModifiedDate 
      FROM rpd.ProjectDetail pd  INNER JOIN rpd.FundSource fs ON pd.FundSourceId = fs.FundSourceId  
                                 INNER JOIN rpd.Baseline base ON pd.ProjectId = base.ProjectId  
                                 INNER JOIN rpd.FundEntityBaseline feb ON feb.BaselineId = base.BaselineId  
      GROUP BY pd.ProjectAux1, pd.ProjectId, pd.ProjectName, pd.ProjectComments, pd.VersionType)
WHERE VersionType Like '%Text%' WITH UR

这里有3个表格的模式(不包括FundSource,因为它只有~200行,我认为它可以忽略不计)

架构:

FundEntityBaseline ProjectDetail Baseline

行:

  • FundEntityBaseline:354603
  • 基线:80208
  • ProjectDetail:1813

ProjectDetail指数:

  • 1主键索引(ProjectId)
  • 1外键索引(FundSourceId)
  • 1包含SELECT / GROUP BY列的索引(ProjectAux1, ProjectId,ProjectName,ProjectComments,VersionType)
  • 1个带有(VersionType,ProjectName)的索引

基线指数:

  • 1主键索引(BaselineId)
  • 1外键索引(ProjectId)
  • 1个带有(ProjectTeamId,ProjectMonth)的索引
  • 仅限ProjectMonth的1个索引

FundEntityBaseline上的指数

  • 1主键索引(FundEntityBaselineId)
  • 1外键索引(BaselineId)

最新的访问计划: Access Plan

2 个答案:

答案 0 :(得分:0)

将where子句(WHERE VersionType,类似'%Text%)移到行上,这样它就会在内部SQL语句中。现在的方式是,您的查询将首先进行所有可能的连接,然后使用where子句过滤该完整集。

所以你的陈述就像

WHERE pd.VersionType Like '%Text%'
GROUP BY .....

答案 1 :(得分:0)

在页面大小为32K的表空间中放置(=重新创建)索引 - 如果尚未配置的话。