我想看看对公交车的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
答案 0 :(得分: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索引,这应该加速查询。
答案 1 :(得分: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'
答案 2 :(得分:0)
除了将查询更改为使用连接而不是子查询(如已建议的那样)之外,您还可以尝试