请优化此查询

时间:2013-10-01 09:29:55

标签: sql optimization oracle10g query-optimization

SELECT
      B.CE_ID,
      A.PPL_CNTR_ID,
      SUM ( A.NBR_IN ) ENTERS,
      SUM ( A.NBR_OUT ) EXITS,
      A.LOG_TS
      + DECODE ( TO_CHAR ( A.LOG_TS,
                       'mi' ),
               '05', 55
                    / 1440,
               '10', 50
                    / 1440,
               '15', 45
                    / 1440,
               '20', 40
                    / 1440,
               '25', 35
                    / 1440,
               '30', 30
                    / 1440,
               '35', 25
                    / 1440,
               '40', 20
                    / 1440,
               '45', 15
                    / 1440,
               '50', 10
                    / 1440,
               '55', 5
                    / 1440,
               0 )
          TS
FROM
      OUTPUTDB.TPPL_CNTR_TRAFFIC A,
      FLUX.V_CE_PPLCNTR B
WHERE
         A.LOG_TS BETWEEN '07-Sep-13' AND '08-Sep-13'
      AND A.PPL_CNTR_ID = B.PPL_CNTR_ID
      AND B.CE_ID IN (SELECT
                        DISTINCT CE_DPN_ID
                   FROM
                        TCE_RLT
                   START WITH
                        CE_PRN_ID = 5798
                   CONNECT BY
                        PRIOR CE_DPN_ID = CE_PRN_ID)
GROUP BY
      B.CE_ID,
      A.PPL_CNTR_ID,
      A.LOG_TS
      + DECODE ( TO_CHAR ( A.LOG_TS,
                       'mi' ),
               '05', 55
                    / 1440,
               '10', 50
                    / 1440,
               '15', 45
                    / 1440,
               '20', 40
                    / 1440,
               '25', 35
                    / 1440,
               '30', 30
                    / 1440,
               '35', 25
                    / 1440,
               '40', 20
                    / 1440,
               '45', 15
                    / 1440,
               '50', 10
                    / 1440,
               '55', 5
                    / 1440,
               0 )
ORDER BY
      B.CE_ID,
      A.PPL_CNTR_ID,
      A.LOG_TS
      + DECODE ( TO_CHAR ( A.LOG_TS,
                       'mi' ),
               '05', 55
                    / 1440,
               '10', 50
                    / 1440,
               '15', 45
                    / 1440,
               '20', 40
                    / 1440,
               '25', 35
                    / 1440,
               '30', 30
                    / 1440,
               '35', 25
                    / 1440,
               '40', 20
                    / 1440,
               '45', 15
                    / 1440,
               '50', 10
                    / 1440,
               '55', 5
                    / 1440,
               0 )

内部子查询

                   SELECT
                        DISTINCT CE_DPN_ID
                   FROM
                        TCE_RLT
                   START WITH
                        CE_PRN_ID = 5798
                   CONNECT BY
                        PRIOR CE_DPN_ID = CE_PRN_ID

返回970行,但执行需要很长时间,请建议任何替代子句或加入以使其运行得更快。使用的2个表只有一个共同的列,所以我很确定没有交叉加入。

3 个答案:

答案 0 :(得分:1)

  1. 不要在'07 -Sep-13'和'08 -Sep-13'之间使用A.LOG_TS而是使用TO_DATE('07 -09-13','DD-MM-YY')
  2. 尽可能替换DISTINCT查询
  3. 删除排序,即按
  4. 排序

答案 1 :(得分:1)

 A.LOG_TS
  + DECODE ( TO_CHAR ( A.LOG_TS,
                   'mi' ),
           '05', 55
                / 1440,
           '10', 50
                / 1440,
           '15', 45
                / 1440,
           '20', 40
                / 1440,
           '25', 35
                / 1440,
           '30', 30
                / 1440,
           '35', 25
                / 1440,
           '40', 20
                / 1440,
           '45', 15
                / 1440,
           '50', 10
                / 1440,
           '55', 5
                / 1440,
           0 )

可怕的是,在结果中使用A.LOG_TS的正确转换(例如SELECT TO_CHAR(A.LOG_TS,'YYYYMMDDHHMI')TS或任何其他格式,而不使用默认转换)并使用A.LOG_TS本身而不进行无意义的转换GROUP BY和ORDER BY子句。

答案 2 :(得分:1)

                 SELECT
                    DISTINCT CE_DPN_ID
               FROM
                    TCE_RLT
               START WITH
                    CE_PRN_ID = 5798
               CONNECT BY
                    PRIOR CE_DPN_ID = CE_PRN_ID

如果您可以向TCE_RLT添加一个列,那么带有索引的“root”ID会使查询更便宜:

SELECT CE_DPN_ID
FROM TCE_RLT
WHERE ROOT_ID = 5798

这样的字段可以在插入时廉价计算:

INSERT INTO TCE_RLT (CE_DPN_ID, CE_PRN_ID,ROOT_ID) 
    VALUES 5798,5798,5798;
INSERT INTO TCE_RLT (CE_DPN_ID, CE_PRN_ID,ROOT_ID) 
    SELECT 12,34,ROOT_ID FROM TCE_RLT WHERE CE_DPN_ID = 34;