DB2内部查询缓慢但速度快,具有硬编码值

时间:2013-06-03 13:53:00

标签: sql performance db2

我在DB2 sql中遇到了一个奇怪的行为。 (DB2 9.7) Follow是一个获取员工薪水,状态和乐队的示例查询。

SELECT
                EMP.STATUS,
                COUNT(*)               AS EMP_COUNT,
                GRP.GROUP_NAME
FROM
                EMPLOYEE EMP,
                EMPLOYEE_SALARY ES,
                GROUP_TABLE GRP
WHERE
                EMP.SALARY > 
                             (select max(EMP1.SALARY) from  
                             EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
                              date(EMP1.JOIN_DT) = '2013-01-01' 
                              and date(EMP1.DATE_TS) = date(FY.CURRENT_DT) - 2 days)
                AND EMP.SALARY = E.EMPID
                AND E.SALARY_GRP = GRP.BAND_GROUP
                AND GRP.RANGE_SALARY = 'BAND-10'
                GROUP BY
                        EMP.STATUS,
                        GRP.GROUP_NAME

EMP(员工)表包含大约1百万行。其余的表非常小。 查询大约需要10秒才能执行

但是当我对内部查询进行硬编码时

select max(EMP1.SALARY) from  EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
        date(EMP1.JOIN_DT) = '2013-01-01' 
        and date(EMP1.DATE_TS) = date(FY.CURRENT_DT) - 2 days

select max(EMP1.SALARY) from  EMPLOYEE EMP1, FINANCIAL_YEAR FY where 
       date(EMP1.JOIN_DT) = '2013-01-01' 
       and date(EMP1.DATE_TS) = '2013-06-01' 

结果在一秒钟之内!!

“FINANCIAL_YEAR FY”表是一个非常小的表,大约有50行,因此我不知道为什么内部查询在其动态时需要时间,但在我硬编码时非常快

一些额外的信息

  • EMPID是整数
  • DATE_TS是时间戳
  • CURRENT_DT,JOIN_DT是日期
  • Rest all are VARCHAR
  • EMPID已编入索引

1 个答案:

答案 0 :(得分:0)

您可以尝试使用此版本(我假设E引用应该是ES别名,否则语句不应该运行。除此之外,你应该放弃隐含的联接' (以逗号分隔的FROM子句),特别是如果您开始处理LEFT JOIN s。

WITH Maximum_Salary (max) as (SELECT MAX(EMP.SALARY) 
                              FROM EMPLOYEE EMP
                              JOIN FINANCIAL_YEAR FY
                                ON (FY.CURRENT_DT - 2 DAYS) >= EMP.DATE_TS
                                   AND (FY.CURRENT_DT - 1 DAYS) < EMP.DATE_TS
                              WHERE EMP.JOIN_DT = DATE('2013-01-01')

SELECT EMP.STATUS, COUNT(*) AS EMP_COUNT, GRP.GROUP_NAME
FROM EMPLOYEE EMP
JOIN GROUP_TABLE GRP
  ON GRP.RANGE_SALARY = 'BAND-10'
JOIN EMPLOYEE_SALARY ES
  ON ES.EMPID = EMP.SALARY
     AND ES.SALARY_GRP = GRP.BAND_GROUP
JOIN Maximum_Salary 
  ON Maximum_Salary <= EMP.SALARY
GROUP BY EMP.STATUS, GRP.GROUP_NAME

如果您还没有习惯,WITH语法是公用表表达式(或CTE) - 实际上,它是一个内联视图。在某些情况下,这些可以导致创建临时表,但是否则可以节省大量的输入(它们也是如何执行递归查询)。我设法将EMP.DATE_TS的引用转换为可以使用索引的表单(对FY.CURRENT_DT上的日期数学没有帮助,尽管作为一个不应该使用的小表很重要。)

请注意,您可能仍需要执行其他调整,尤其是取决于您可能(不)具有哪些索引。