I have a table that looks like so:
ID | objectID | time | ...
-------------------
1 | 1 | ...
2 | 1 | ...
3 | 1 | ...
4 | 2 | ...
5 | 2 | ...
6 | 3 | ...
7 | 4 | ...
ID is the primary key, objectID is non-unique. I am trying to increase performance on a query to get the most recent entries for all objectIDs, but the entries should not be newer than a certain value. I tried to following two queries, which should both provide the same (and correct results):
SELECT *
FROM (
SELECT *
FROM table
WHERE time <= XXX
ORDER BY time DESC
)
GROUP BY objectID
AND
SELECT *
FROM table AS t
INNER JOIN (
SELECT ID, MAX(time)
FROM table
WHERE time <= 1353143351
GROUP BY objectID
) s
USING (ID)
An EXPLAIN for the first query tells me
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
------------------------------------------------------------------------------------
1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 145827 | Using temporary; Using filesort
2 | DERIVED | tbl_test | ALL | NULL | NULL | NULL | NULL | 238694 | Using filesort
for the second query it says
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
------------------------------------------------------------------------------------
1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 325
1 | PRIMARY | t | eq_ref | PRIMARY,ID | PRIMARY | 4 | s.ID | 1
2 | DERIVED | tbl_test | index | NULL | ID | 12 | NULL | 238694 | Using where; Using index; Using temporary; Using filesort
(tbl_test is my table for testing)
The second query seems to be (much) faster, but still not extreme fast with a runtime of 0.1 secs at ~200k DB entries. Is there a way to increase performance of the query? Any missing indexes?
Thanks in advance!!
Edit: Explain for eggys query (see query in his post):
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 325
1 PRIMARY lab_case_test ALL NULL NULL NULL NULL 238694 Using where; Using join buffer
2 DERIVED lab_case_test index NULL ID 12 NULL 238694 Using where; Using index; Using temporary; Using f...
CREATE TABLE `lab_case_test` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`caseID` int(11) NOT NULL,
`time` int(11) NOT NULL,
// ....
PRIMARY KEY (`ID`),
KEY `ID` (`ID`,`caseID`,`time`),
KEY `caseID` (`caseID`,`time`)
) ENGINE=MyISAM AUTO_INCREMENT=238695 DEFAULT CHARSET=utf8
You want a composite index over
(objectID, time)
:The reason for this is that MySQL can then retrieve the maximum
time
for eachobjectID
directly from the index tree; it can then also use the same index in joining against the table again to find the groupwise maximum records using something like your second query (but one should join on bothobjectID
andtime
—I like to use aNATURAL JOIN
in cases like this):