Оптимизируйте этот запрос, пожалуйста

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 строк, но выполнение занимает очень много времени. Пожалуйста, предложите любое альтернативное предложение или объединение, чтобы оно выполнялось быстрее. Две использованные таблицы имеют только один общий столбец, так что я уверен, что перекрестного соединения не происходит.

3 ответа

  1. Не используйте A.LOG_TS МЕЖДУ '07-Sep-13'И '08-Sep-13', а используйте TO_DATE( '07-09-13', 'DD-MM-YY')
  2. Замените запрос DISTINCT, если это возможно
  3. Удалить сортировку, т.е. упорядочить по
 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.

                 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, "корневой" идентификатор, снабженный индексом, сделает запрос дешевле:

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;
Другие вопросы по тегам