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是数字字段)