2012-07-12 66 views
1

我想知道對總線的ETA進行的預測是否有實際的消息。我寫了這個查詢並超時。難道我做錯了什麼?有什麼優化可以幫助嗎?Oracle中的查詢超時

SELECT 
P.ROUTE, 
P.CODE, 
(
    SELECT COUNT(*) 
    FROM MESSAGE M 
    WHERE M.SENTDATE BETWEEN P.ARRIVAL-(20/60/24) AND P.ARRIVAL+(2/60/24) 
    AND TRIM(SUBSTR(M.LOCATIONINFO, 3, 10)) = P.ROUTE 
    AND TRIM(SUBSTR(M.LOCATIONINFO, 25, 10)) = P.CODE 
) 
CNT 
FROM 
(
    SELECT * 
    FROM PREDICTION P 
    WHERE P.ARRIVAL BETWEEN TO_DATE('2012/07/04 04:30:00', 'YYYY/MM/DD HH24:MI:SS') 
    AND TO_DATE('2012/07/04 04:30:10', 'YYYY/MM/DD HH24:MI:SS') 
    AND P.ROUTE ='7' 
    AND P.CODE ='2179' 
) 
P 
+0

的編輯,但它的方式@notfed謝謝是;由Oracle自己格式化。 – 2012-07-12 15:07:09

回答

0

試試這個,看看它是否解決了問題(和結果是正確的!):

SELECT COUNT(M.*) CNT 
FROM 
    PREDICTION P 
INNER JOIN 
    MESSAGE M 
ON M.SENTDATE BETWEEN P.ARRIVAL-(20/60/24) AND P.ARRIVAL+(2/60/24) 
AND TRIM(SUBSTR(M.LOCATIONINFO, 3, 10)) = P.ROUTE       
AND TRIM(SUBSTR(M.LOCATIONINFO, 25, 10)) = P.CODE 
WHERE P.ARRIVAL BETWEEN TO_DATE('2012/07/04 04:30:00', 'YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2012/07/04 04:30:10', 'YYYY/MM/DD HH24:MI:SS')       
AND P.ROUTE ='7'       
AND P.CODE ='2179' 
+0

謝謝;但用COUNT(M. *)它不起作用,用COUNT(*)它超時。 – 2012-07-12 15:02:15

+0

你可以試試COUNT(M.CODE)或類似的東西嗎?我不知道你的模式,所以我不知道它對你是否可行! – 2012-07-12 15:08:10

+0

它沒有工作:(我也編輯了查詢也謝謝 – 2012-07-12 15:14:53

1

要真正知道是怎麼回事,我們需要看到的查詢計劃。在此期間,嘗試重寫您的查詢以獲得明確加入:

SELECT COUNT(*) as cnt 
FROM (SELECT * 
     FROM PREDICTION P 
     WHERE P.ARRIVAL BETWEEN TO_DATE('2012/07/04 04:30:00', 'YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2012/07/04 04:30:10', 'YYYY/MM/DD HH24:MI:SS')AND 
      P.ROUTE ='7' AND 
      P.CODE ='2179' 
    ) P join 
    MESSAGE M 
    on M.SENTDATE BETWEEN P.ARRIVAL-(20/60/24) AND P.ARRIVAL+(2/60/24) AND 
     TRIM(SUBSTR(M.LOCATIONINFO, 3, 10)) = P.ROUTE AND 
     TRIM(SUBSTR(M.LOCATIONINFO, 25, 10)) = P.CODE 

您正在進行相當複雜的連接。兩張桌子有多大?他們有沒有索引?

我會建議嘗試:

SELECT COUNT(*) as cnt 
FROM (SELECT * 
     FROM PREDICTION P 
     WHERE P.ARRIVAL BETWEEN TO_DATE('2012/07/04 04:30:00', 'YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2012/07/04 04:30:10', 'YYYY/MM/DD HH24:MI:SS')AND 
      P.ROUTE ='7' AND 
      P.CODE ='2179' 
    ) P join 
    MESSAGE M 
    on M.SENTDATE BETWEEN P.ARRIVAL-(20/60/24) AND P.ARRIVAL+(2/60/24) AND 
     TRIM(SUBSTR(M.LOCATIONINFO, 3, 10)) = '7' AND 
     TRIM(SUBSTR(M.LOCATIONINFO, 25, 10)) = '2179' 

這些是等價的。但是,在最初的情況下,Oracle可能會看到一個複雜的三部分連接,並沒有使用正確的索引。在第二種情況下,它應該使用SENTDATE索引,這會加快查詢速度。

+0

消息表是非常非常大,但有一些索引(例如在SENTDATE).PREDICTION表不是太大,但它也有索引(在ARRIVAL,代碼,路由和MADEAT)。 – 2012-07-12 15:04:02

0

除了改變您的查詢中使用聯接,而不是一個子查詢(如已經建議),你也可以嘗試

  • 在擺脫裝飾(SUBSTR(...))的比較路由和代碼,因爲這將使得在locationinfo無用
  • 任何索引擺脫引號7和2179(假設路線和代碼是數字字段)