MySQL:获取早于xxx的最新条目,性能
我有一个看起来像这样的表:
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是主键,objectID是唯一的. 我试图提高查询的性能,以获取所有objectID的最新条目,但条目不应比特定值新. 我尝试遵循以下两个查询,这两个查询都应提供相同(和正确的结果):
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
它说的第二个查询
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是我要测试的表)
(tbl_test is my table for testing)
第二个查询似乎(快得多),但是在200k DB条目下运行时间为0.1秒,仍然不是非常快. 有没有办法提高查询性能?缺少索引吗?
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?
提前谢谢!
解释eggys查询(请参阅他的帖子中的查询):
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
您要在(objectID, time)
上使用复合索引:
You want a composite index over (objectID, time)
:
ALTER TABLE my_table ADD INDEX (objectID, time)
这样做的原因是MySQL可以直接从索引树中检索每个objectID
的最大值.然后,它还可以使用相同的索引再次针对该表进行连接,以找到
The reason for this is that MySQL can then retrieve the maximum time
for each objectID
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 both objectID
and time
—I like to use a NATURAL JOIN
in cases like this):
SELECT *
FROM my_table NATURAL JOIN (
SELECT objectID, MAX(time) time
FROM my_table
WHERE time <= 1353143351
GROUP BY objectID
) t