1

バスの ETA に対して行われた予測に実際のメッセージがあるかどうかを確認したいと考えています。このクエリを書きましたが、タイムアウトします。私は何か間違ったことをしていますか?ここで役立つ最適化はありますか?

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
4

3 に答える 3

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

かなり複雑な結合を行っています。2つのテーブルの大きさは? インデックスはありますか?

試してみることをお勧めします:

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 は複雑な 3 部構成の結合を認識し、適切なインデックスを使用しない場合があります。2 番目のケースでは、クエリを高速化する SENTDATE インデックスを使用する必要があります。

于 2012-07-12T14:38:18.440 に答える
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'
于 2012-07-12T14:35:14.420 に答える
0

サブクエリではなく結合を使用するようにクエリを変更することとは別に(すでに提案されているように)、次のことを試みることもできます

  • route と code の比較で trim(substr(...)) を削除します。これにより、locationinfo のインデックスが役に立たなくなるためです。
  • 7 と 2179 の周りの引用符を取り除きます (ルートとコードが数値フィールドであると仮定します)
于 2012-07-12T14:44:39.497 に答える