2016-02-10 6 views
1

Я столкнулся с проблемой производительности при запуске следующего сценария. Для выполнения этого запроса требуется много времени, более 1 часа.Как передать условие where во вложенном запросе

CREATE OR REPLACE VIEW VW_TEST AS 
SELECT UNID AS UNIT_ID,AG_ID,STATION,EID,NUM_1 AS EVENT_NUMBER, 
(TO_DATE(SUBSTR(DP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS DP, 
(TO_DATE(SUBSTR(ER,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS ER, 
(TO_DATE(SUBSTR(AR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AR, 
(TO_DATE(SUBSTR(TR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TR, 
(TO_DATE(SUBSTR(TA,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TA, 
(TO_DATE(SUBSTR(TP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TP, 
(TO_DATE(SUBSTR(PS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS PS, 
(TO_DATE(SUBSTR(TG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TG, 
(TO_DATE(SUBSTR(AG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AG, 
(TO_DATE(SUBSTR(HB,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS HB, 
(TO_DATE(SUBSTR(TO_LOC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TO_LOC, 
(TO_DATE(SUBSTR(AO,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AO, 
(TO_DATE(SUBSTR(TC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TC, 
(TO_DATE(SUBSTR(AC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AC, 
(TO_DATE(SUBSTR(AM,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AM, 
(TO_DATE(SUBSTR(OS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS OS, 
TRIP_NO 
FROM (
SELECT * FROM (SELECT u.UNID, u.AG_ID, u.STATION ,u.EID, u.NUM_1, u.CDTS,u.UNIT_STATUS,ATH_TRIP_NO(u.RECOVERY_CDTS,u.EID,u.NUM_1,u.UNID) TRIP_NO 
FROM UN_HI u 
WHERE u.RECOVERY_CDTS IN(SELECT MAX(RECOVERY_CDTS) AS RECOVERY_CDTS FROM UN_HI GROUP BY UNID,AG_ID,STATION,EID,UNIT_STATUS,ATH_TRIP_NO(RECOVERY_CDTS,EID,NUM_1,UNID)) 
) 
PIVOT (MIN(CDTS) FOR (UNIT_STATUS) IN ('DP' DP,'ER' ER, 'AR' AR,'TR' TR,'TA' TA,'TP' TP,'PS' PS,'TG' TG,'AG' AG,'HB' HB,'TO' TO_LOC,'AO' AO,'TC' TC,'AC' AC,'AM' AM,'OS' OS))) t1 
GROUP BY UNID,AG_ID,STATION,EID,NUM_1,DP,ER,AR,TR,TA,TP,PS,TG,AG,HB,TO_LOC,AO,TC,AC,AM,OS,TRIP_NO 
ORDER BY EID,UNID,TRIP_NO 

Когда я бегу:

SELECT * FROM VW_TEST WHERE EID = 58100 

Тогда это занимает больше, чем за 1 час.

Но когда я передаю условие where внутри вложенного запроса, я получаю результат в течение 5 секунд.

SELECT UNID AS UNIT_ID,AG_ID,STATION,EID,NUM_1 AS EVENT_NUMBER, 
(TO_DATE(SUBSTR(DP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS DP, 
(TO_DATE(SUBSTR(ER,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS ER, 
(TO_DATE(SUBSTR(AR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AR, 
(TO_DATE(SUBSTR(TR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TR, 
(TO_DATE(SUBSTR(TA,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TA, 
(TO_DATE(SUBSTR(TP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TP, 
(TO_DATE(SUBSTR(PS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS PS, 
(TO_DATE(SUBSTR(TG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TG, 
(TO_DATE(SUBSTR(AG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AG, 
(TO_DATE(SUBSTR(HB,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS HB, 
(TO_DATE(SUBSTR(TO_LOC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TO_LOC, 
(TO_DATE(SUBSTR(AO,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AO, 
(TO_DATE(SUBSTR(TC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TC, 
(TO_DATE(SUBSTR(AC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AC, 
(TO_DATE(SUBSTR(AM,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AM, 
(TO_DATE(SUBSTR(OS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS OS, 
TRIP_NO 
FROM (
SELECT * FROM (SELECT u.UNID, u.AG_ID, u.STATION ,u.EID, u.NUM_1, u.CDTS,u.UNIT_STATUS,ATH_TRIP_NO(u.RECOVERY_CDTS,u.EID,u.NUM_1,u.UNID) TRIP_NO 
FROM UN_HI u 
WHERE u.EID = 58100 AND u.RECOVERY_CDTS IN(SELECT MAX(RECOVERY_CDTS) AS RECOVERY_CDTS FROM UN_HI WHERE EID = 58100 GROUP BY UNID,AG_ID,STATION,EID,UNIT_STATUS,ATH_TRIP_NO(RECOVERY_CDTS,EID,NUM_1,UNID)) 
) 
PIVOT (MIN(CDTS) FOR (UNIT_STATUS) IN ('DP' DP,'ER' ER, 'AR' AR,'TR' TR,'TA' TA,'TP' TP,'PS' PS,'TG' TG,'AG' AG,'HB' HB,'TO' TO_LOC,'AO' AO,'TC' TC,'AC' AC,'AM' AM,'OS' OS))) t1 
GROUP BY UNID,AG_ID,STATION,EID,NUM_1,DP,ER,AR,TR,TA,TP,PS,TG,AG,HB,TO_LOC,AO,TC,AC,AM,OS,TRIP_NO 
ORDER BY EID,UNID,TRIP_NO 

Но проблема в том, что мне нужно использовать его как представление и не могу использовать этот большой запрос в своем приложении. Любые предложения будут высоко оценены.

+2

Если вы отметите СУБД вы используете, вы, вероятно, получите больше внимания ... (Некоторые не-ANSI SQL там ...) – jarlh

+0

Учитывая то, как OP написал статью PIVOT она должна быть оракул, по крайней мере, версия 11g. –

ответ

0

Если используемая СУБД поддерживает материализованные представления, вы можете использовать их, чтобы результат был уже рассчитан в момент запроса базы данных. Например, в Oracle-подобных СУБД, вы можете использовать что-то вроде:

CREATE MATERIALIZED VIEW VW_TEST 
REFRESH ON DEMAND 
START WITH SYSDATE 
NEXT SYSDATE + 1 
AS 
SELECT UNID AS UNIT_ID,AG_ID,STATION,EID,NUM_1 AS EVENT_NUMBER, 
(TO_DATE(SUBSTR(DP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS DP, 
(TO_DATE(SUBSTR(ER,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS ER, 
(TO_DATE(SUBSTR(AR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AR, 
(TO_DATE(SUBSTR(TR,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TR, 
(TO_DATE(SUBSTR(TA,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TA, 
(TO_DATE(SUBSTR(TP,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TP, 
(TO_DATE(SUBSTR(PS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS PS, 
(TO_DATE(SUBSTR(TG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TG, 
(TO_DATE(SUBSTR(AG,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AG, 
(TO_DATE(SUBSTR(HB,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS HB, 
(TO_DATE(SUBSTR(TO_LOC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TO_LOC, 
(TO_DATE(SUBSTR(AO,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AO, 
(TO_DATE(SUBSTR(TC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS TC, 
(TO_DATE(SUBSTR(AC,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AC, 
(TO_DATE(SUBSTR(AM,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS AM, 
(TO_DATE(SUBSTR(OS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) AS OS, 
TRIP_NO 
FROM (
SELECT * FROM (SELECT u.UNID, u.AG_ID, u.STATION ,u.EID, u.NUM_1, u.CDTS,u.UNIT_STATUS,ATH_TRIP_NO(u.RECOVERY_CDTS,u.EID,u.NUM_1,u.UNID) TRIP_NO 
FROM UN_HI u 
WHERE u.RECOVERY_CDTS IN(SELECT MAX(RECOVERY_CDTS) AS RECOVERY_CDTS FROM UN_HI GROUP BY UNID,AG_ID,STATION,EID,UNIT_STATUS,ATH_TRIP_NO(RECOVERY_CDTS,EID,NUM_1,UNID)) 
) 
PIVOT (MIN(CDTS) FOR (UNIT_STATUS) IN ('DP' DP,'ER' ER, 'AR' AR,'TR' TR,'TA' TA,'TP' TP,'PS' PS,'TG' TG,'AG' AG,'HB' HB,'TO' TO_LOC,'AO' AO,'TC' TC,'AC' AC,'AM' AM,'OS' OS))) t1 
GROUP BY UNID,AG_ID,STATION,EID,NUM_1,DP,ER,AR,TR,TA,TP,PS,TG,AG,HB,TO_LOC,AO,TC,AC,AM,OS,TRIP_NO 
ORDER BY EID,UNID,TRIP_NO 

Это освежит ваш взгляд один раз в день, вы можете адаптировать его для ваших потребностей.

0

В качестве первого варианта я попытался бы проверить, может ли переписать запрос таким образом, чтобы оптимизатор мог нажимать условия на EID на наиболее вложенный подзапрос, чтобы решить проблему. Следующее, где EID используется в оценке полусоединения (предложение IN), должно быть хорошо для этого. Я не могу гарантировать, что это правильно, потому что я не могу попробовать, но я вполне уверен в этом. Вы должны проверить это.

SELECT UNID AS UNIT_ID,AG_ID,STATION,EID,NUM_1 AS EVENT_NUMBER, 
    DP, ER, AR, TR, TA, TP, PS, TG, AG, HB, TO_LOC, AO, TC, AC, AM, OS, 
    TRIP_NO 
FROM (
     SELECT * 
     FROM (
       SELECT u.UNID, u.AG_ID, u.STATION ,u.EID, u.NUM_1, 
        (TO_DATE(SUBSTR(u.CDTS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) as CDTS, 
        u.UNIT_STATUS, 
        ATH_TRIP_NO(u.RECOVERY_CDTS,u.EID,u.NUM_1,u.UNID) TRIP_NO 
       FROM UN_HI u 
       WHERE (UNIT_STATUS) IN (
         'DP','ER', 'AR','TR','TA','TP','PS','TG','AG','HB', 
         'TO_LOC','AO','TC','AC','AM','OS' 
        ) 
        and (u.EID, u.RECOVERY_CDTS) IN(
         SELECT u.EID,MAX(RECOVERY_CDTS) AS RECOVERY_CDTS 
         FROM UN_HI 
         GROUP BY u.EID,UNID,AG_ID,STATION,EID,UNIT_STATUS,ATH_TRIP_NO(RECOVERY_CDTS,EID,NUM_1,UNID) 
        ) 
      ) 
     PIVOT (
      MIN(CDTS) 
      FOR (UNIT_STATUS) IN (
       'DP' DP,'ER' ER, 'AR' AR,'TR' TR,'TA' TA,'TP' TP,'PS' PS,'TG' TG,'AG' AG,'HB' HB, 
       'TO' TO_LOC,'AO' AO,'TC' TC,'AC' AC,'AM' AM,'OS' OS 
      ) 
     ) 
    ) t1 
GROUP BY UNID,AG_ID,STATION,EID,NUM_1,DP,ER,AR,TR,TA,TP,PS,TG,AG,HB,TO_LOC,AO,TC,AC,AM,OS,TRIP_NO 
ORDER BY EID,UNID,TRIP_NO 

Тогда я пятно, что вы используете «само Полусоединение», чтобы найти MIN (CDTS) только среди тех из них, разделяющих наибольшее значение на RECOVERY_CDTS, которые могут быть найдены в более простым способом, используя функцию LAST, поэтому вы можете попробовать этот другой запрос, который должен быть также быстрее, чем предыдущий, и ваш оригинальный.

SELECT UNID AS UNIT_ID,AG_ID,STATION,EID,NUM_1 AS EVENT_NUMBER, 
    DP, ER, AR, TR, TA, TP, PS, TG, AG, HB, TO_LOC, AO, TC, AC, AM, OS, 
    TRIP_NO 
FROM (
     SELECT * 
     FROM (
       SELECT u.UNID, u.AG_ID, u.STATION ,u.EID, u.NUM_1, 
        u.UNIT_STATUS, 
        ATH_TRIP_NO(u.RECOVERY_CDTS,u.EID,u.NUM_1,u.UNID) TRIP_NO, 
        min(TO_DATE(SUBSTR(u.CDTS,0,14),'YYYY/MM/dd HH24:MI:SS')+3/24) keep (dense_rank least order by RECOVERY_CDTS)as CDTS 
       FROM UN_HI u 
       where (UNIT_STATUS) IN (
        'DP','ER', 'AR','TR','TA','TP','PS','TG','AG','HB', 
        'TO_LOC','AO','TC','AC','AM','OS' 
       ) 
       GROUP BY UNID,AG_ID,STATION,EID,UNIT_STATUS,ATH_TRIP_NO(RECOVERY_CDTS,EID,NUM_1,UNID) 
      ) 
     PIVOT (
      MIN(CDTS) 
      FOR (UNIT_STATUS) IN (
       'DP' DP,'ER' ER, 'AR' AR,'TR' TR,'TA' TA,'TP' TP,'PS' PS,'TG' TG,'AG' AG,'HB' HB, 
       'TO' TO_LOC,'AO' AO,'TC' TC,'AC' AC,'AM' AM,'OS' OS 
      ) 
     ) 
    ) t1 
GROUP BY UNID,AG_ID,STATION,EID,NUM_1,DP,ER,AR,TR,TA,TP,PS,TG,AG,HB,TO_LOC,AO,TC,AC,AM,OS,TRIP_NO 
ORDER BY EID,UNID,TRIP_NO 
Смежные вопросы