2

美好的一天,我有一个我一直在努力解决的问题,希望有人已经找到了一个聪明的解决方案(我使用 MySQL)。

我有这样的表:

Table `log`
----------
id
inserted
message
user_id

我的目标是为用户选择最后插入的记录并使其快速。日志表很大(大约 90 万条记录),所以我的第一个方法是:

SELECT * FROM `log` 
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN 
(
 SELECT MAX(`id`) FROM `log` GROUP BY `user_id`
)

但似乎它为每一行计算子查询(EXPLAIN 显示 DEPENDENT QUERY)。当我将此查询拆分为两个时:

SELECT MAX(`id`) FROM `log` GROUP BY `user_id`

SELECT * FROM `log` 
LEFT JOIN `users` ON `users`.`id` = `log`.`user_id`
WHERE `id` IN (....ids from first query...)

跑步是可以接受的。这可以通过一个查询来实现吗?

4

4 回答 4

4

怎么样

SELECT user_id, max(id) FROM `log` GROUP BY user_id

?

这将为您提供日志表中每个用户的最大 ID,一次查询!

于 2010-02-09T21:13:00.357 回答
1

如果您总是在寻找特定用户的日志,那么按 user_id 对日志文件进行分区会大大加快速度。如果表是按用户分区并按id索引的,查询将运行得非常快。

编辑:见多米尼克的查询

于 2010-02-09T21:13:48.240 回答
1

除了使用 group by 来获取分组最大值之外,您可能还希望将其设为不相关的子查询,以从表中获取特定行的附加字段。

SELECT
  la.user_id,la.message
FROM
  `log` as la
INNER JOIN
  (
    SELECT
      user_id, MAX(id) AS maxid
    FROM
      `log`
    GROUP BY
      user_id
    ) as lb
ON
  la.id = lb.maxid

如果您有索引,这效果最好/最快

KEY `foo` (`user_id`,`id`)

但即使没有那个键,性能也会下降。

于 2010-02-09T21:55:56.583 回答
0

此外,我会确保您在 user_id 上有一个索引。

编辑:广义

于 2010-02-09T21:15:52.307 回答