我有一张看起来像这样的表
ID | identifier | data | created_at
------------------------------------
1 | 500 | test1 | 2011-08-30 15:27:29
2 | 501 | test1 | 2011-08-30 15:27:29
3 | 500 | test2 | 2011-08-30 15:28:29
4 | 865 | test3 | 2011-08-30 15:29:29
5 | 501 | test2 | 2011-08-30 15:31:29
6 | 500 | test3 | 2011-08-30 15:31:29
我需要的是每个标识符的最新条目,可以通过ID或created_at中的日期来决定。由于索引,我认为ID是更好的选择。
我希望这个结果集:
4 | 865 | test3 | 2011-08-30 15:29:29
5 | 501 | test2 | 2011-08-30 15:31:29
6 | 500 | test3 | 2011-08-30 15:31:29
结果应按日期或ID按升序排序。
这是一个包含大约8百万行的表格,这很重要。
我现在尝试了一些自我加入和子查询的方法。不幸的是,所有这些都是错误的结果或运行时间的五十年。
举个例子:
SELECT lo1.*
FROM table lo1
INNER JOIN
(
SELECT MAX(id) MaxID, identifier, id
FROM table
GROUP BY identifier
) lo2
ON lo1.identifier= lo2.identifier
AND lo1.id = lo2.MaxID
ORDER BY lo1.id DESC
LIMIT 10
以上查询需要很长时间,有时不会返回标识符的最新结果,但不太确定原因。
有没有人能够获取所需的结果集,最好不需要十年?
如所询问的,这是创建代码:
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`identifier` int(11) NOT NULL,
`data` varchar(200) COLLATE latin1_bin NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `identifier` (`identifier`),
KEY `created_at` (`created_at`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
答案 0 :(得分:2)
提供正确结果的正确查询,但不会在较大的表上进行缩放。
<强>查询强>
SELECT
`table`.*
FROM
`table`
INNER JOIN
(
SELECT
MAX(id) AS MaxID
, identifier
FROM
`table`
GROUP BY
identifier
#disables GROUP BY Sorting might make the query faster.
ORDER BY
NULL
) `table_group`
ON
`table`.ID = `table_group`.MaxID
ORDER BY
`table`.ID DESC
LIMIT 10
<强>结果强>
| id | identifier | data | created_at |
|----|------------|-------|----------------------|
| 6 | 500 | test3 | 2011-08-30T15:31:29Z |
| 5 | 501 | test2 | 2011-08-30T15:31:29Z |
| 4 | 865 | test3 | 2011-08-30T15:29:29Z |
参见演示http://www.sqlfiddle.com/#!9/7f4401/4
但是当您检查“查看执行计划”时,您可以在额外列中看到“使用where;使用临时;使用filesort”意味着MySQL需要使用快速排序算法“使用临时”;表示快速排序算法首先在内存临时表上运行
如果内存临时表变大,它将转换为磁盘临时表上的MyISAM。
这意味着快速排序将需要基于磁盘的随机i / o来排序磁盘上的速度很慢。
所以这个方法不会在表上扩展到大约8百万行。
下面的查询也会给出相同的结果,但应该进行更优化
<强>查询强>
SELECT
`table`.*
FROM
`table`
INNER JOIN (
SELECT
`table`.ID
FROM
`table`
INNER JOIN
(
SELECT
MAX(id) AS MaxID
, identifier
FROM
`table`
GROUP BY
identifier
#disables GROUP BY Sorting might make the query faster.
ORDER BY
NULL
)
AS `table_group`
ON
`table`.ID = `table_group`.MaxID
)
AS `table_group_max`
ON
`table`.ID = `table_group_max`.ID
ORDER BY
`table`.ID DESC
LIMIT 10
<强>结果强>
| id | identifier | data | created_at |
|----|------------|-------|----------------------|
| 6 | 500 | test3 | 2011-08-30T15:31:29Z |
| 5 | 501 | test2 | 2011-08-30T15:31:29Z |
| 4 | 865 | test3 | 2011-08-30T15:29:29Z |
参见演示http://www.sqlfiddle.com/#!9/7f4401/21
当您选中“查看执行计划”时,不再有“使用临时;使用文件”,这意味着查询应该比上一个查询更优化,理论上应该执行得更快。
因为组合“使用临时;使用filesort”确实可以像解释一样成为性能杀手。