Sql Oracle中的查询超时

Sql Oracle中的查询超时,sql,database,oracle,stored-procedures,Sql,Database,Oracle,Stored Procedures,我想看看对公共汽车预计到达时间的预测是否有实际的信息。我写了这个查询,它超时了。我做错什么了吗?这里有什么优化方法可以帮助你吗 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

我想看看对公共汽车预计到达时间的预测是否有实际的信息。我写了这个查询,它超时了。我做错什么了吗?这里有什么优化方法可以帮助你吗

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

试试这个,看看它是否解决了问题(并且结果是正确的!):


试试这个,看看它是否解决了问题(并且结果是正确的!):


要真正了解发生了什么,我们需要查看查询计划。同时,请尝试重写查询以获得显式联接:

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索引,这将加快查询速度。

要真正了解发生了什么,我们需要查看查询计划。同时,请尝试重写查询以获得显式联接:

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索引,这将加快查询速度。

除了将查询更改为使用联接而不是子查询(正如已经建议的那样),您还可以尝试

  • 去掉route和code比较中的trim(substr(…),因为这将使locationinfo上的任何索引都无用
  • 去掉7和2179左右的引号(假设route和code是数字字段)

除了将查询更改为使用联接而不是子查询(正如已经建议的那样),您还可以尝试

  • 去掉route和code比较中的trim(substr(…),因为这将使locationinfo上的任何索引都无用
  • 去掉7和2179左右的引号(假设route和code是数字字段)

谢谢;但是使用COUNT(M*)时它不起作用,而使用COUNT(*)时它超时。您可以尝试使用COUNT(M.CODE)或类似的方法吗?我不知道你的模式,所以我不知道它对你是否可行!它也不起作用:(我也编辑了查询。谢谢谢谢谢谢;但是使用COUNT(M*)它不起作用,而使用COUNT(*)它会超时。您可以尝试使用COUNT(M.CODE)或类似的东西吗?我不知道您的模式,所以我不知道它是否对您可行!它也不起作用:(我也编辑了查询。ThanksMessage表非常大,但有一些索引(例如在SENTDATE上)。PREDICTION表不是很大,但也有索引(到达时、代码、路由和MADEAT)。Message表非常大,但有一些索引(例如在SENTDATE上).PREDICTION表不是很大,但它也有索引(到达时、代码、路由和MADEAT)。@notfed感谢您的编辑,但它的格式是由Oracle自己设置的。@notfed感谢您的编辑,但它的格式是由Oracle自己设置的。