I see a big difference in speed between these two queries; the first one runs in 0.3 seconds, and the second in 76 seconds.
The first query only selects the key, whereas the second query select an additional field, which is an int(11). I can substitute the second field for any other field, same result. Selecting only the key is much faster for some reason? Can anyone possibly explain the huge difference in speed? I'm stumped by this.
Q1:
SELECT ID
FROM TRMSMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
Q2:
SELECT ID, Chanid
FROMTRM SMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
Regards
I suppose you have an index on your CallStarted
column and ID
is the primary key. Your first query can do a so-called range scan on that index, and retrieve the row identities quickly because secondary indexes on InnoDB also include the primary key.
So it ends up doing just a little bit of work.
Your second query has to fetch data from the main table. In particular it has to fetch the ChanID
variable. It then has to sort the whole mess, grab 50 values from the end, and discard the rest of the sort.
Do a deferred join to pick up the extra columns. That is, just sort the ID numbers, then grab the rest of the data you need from the table. That way you only have to grab 50 rows' worth of data.
Like so:
SELECT a.ID, a.Chanid, a.WhatEver, a.WhatElse
FROM TRMSMain.tblcalldata a
JOIN (
SELECT ID
FROM TRMSMain.tblcalldata
WHERE CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59'
ORDER BY ID DESC
LIMIT 0, 50
) b ON a.ID = b.ID
ORDER BY a.ID DESC
You know the inner query is fast; you've proven that. The JOIN
merely exploits that quickness (based on good use of indexes) to get the detail data for the rows it needs.
Pro tip: Avoid BETWEEN
for date/time ranges, because as you know it handles the end of the range poorly. This will perform just as well and avoid the 59:59
nonsense.
WHERE CallStarted >= '2014/06/13'
AND CallStarted < '2014/06/13' + INTERVAL 1 DAY
It grabs records starting at midnight on June 13, and gets them all up to but not including (<
) midnight on the next day.