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