问题
Guys, im more of a MSSQL guy but im working on some MYSQL right now.
Iv written a simple query, with a subquery and I cant understand for the life of me why its so slow.
This query:
SELECT MAX(timestamp), user, status FROM checkin WHERE room_id = 'Room Name' AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND) GROUP BY user
Runs in 0.0034 seconds
Yet this relatively similiar query but nested, takes over 6 seconds ..
SELECT user, status FROM checkin
WHERE timestamp IN
(SELECT MAX(timestamp) FROM checkin WHERE room_id = 'Room Name' AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND) GROUP BY user)
Can anyone please help? Im stuck.
The table "checkin" only has about 900 rows in it. only the room_id column is indexed.
Cheers
EDIT Thanks guys .. heres the result of the EXPLAIN
DEPENDENT SUBQUERY checkin ref room_id room_id 202 const 1104 Using where; Using temporary; Using filesort
回答1:
Look into using a HAVING
clause to achieve the same results. MySQL is notoriously bad at sub-query optimization, try this:
SELECT MAX(timestamp) as ts, user, status
FROM checkin
WHERE room_id = 'Room Name'
AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND)
GROUP BY user
HAVING timestamp = ts
also make sure that there is an index on timestamp
Alternatively:
SELECT user, status
FROM checkin
WHERE room_id = 'Room Name'
AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND)
AND NOT EXISTS (SELECT * FROM checkin as newer
WHERE newer.timestamp>checkin.timestamp
AND newer.room_id = 'Room Name'
AND newer.user = checkin.user)
GROUP BY user
回答2:
I think, that you are dealing with dependent subquery. This means, that subquery is not executed once (as you and I would expect), but for every row - it is a known bug of MySQL. If you can, split it into two queries - find out the MAX value first and then do a selection.
回答3:
Please run EXPLAIN on both queries. Propably you dont have proper indexes on your columns.
Try that:
EXPLAIN SELECT user, status FROM checkin WHERE timestamp IN (SELECT MAX(timestamp) FROM checkin WHERE room_id = 'Room Name' AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND) GROUP BY user);
And:
SELECT MAX(timestamp) FROM checkin WHERE room_id = 'Room Name' AND timestamp > DATE_SUB(Now() ,INTERVAL 4005 SECOND) GROUP BY user
来源:https://stackoverflow.com/questions/5960901/very-slow-mysql-sub-query