仅从表中选择最新记录并使其快速,如何?

Posted

技术标签:

【中文标题】仅从表中选择最新记录并使其快速,如何?【英文标题】:Select only newest records from table and make this FAST, how? 【发布时间】:2011-01-15 00:11:15 【问题描述】:

美好的一天,我有一个一直在苦苦挣扎的问题,希望有人已经找到了一个聪明的解决方案(我使用 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...)

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

【问题讨论】:

【参考方案1】:

怎么样

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

?

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

【讨论】:

查看我的答案以加快速度。 但是message这个字段呢?这可能也应该在结果集中。 是的,VolkerK 是对的,我还需要其他字段(如 message)。【参考方案2】:

除了使用 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`)

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

【讨论】:

有效!万分感谢!这真是用SQL的方式思考! 请记住,我不是(我的)SQL 专家。其他人完全有可能提出更好的解决方案(+指出此解决方案的问题)。我冒昧地更改了标签,希望“引诱”(甚至)更多专家回答这个问题;-)【参考方案3】:

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

编辑:查看 Dominik 的查询

【讨论】:

【参考方案4】:

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

编辑:概括

【讨论】:

以上是关于仅从表中选择最新记录并使其快速,如何?的主要内容,如果未能解决你的问题,请参考以下文章

仅从表中选择一些列

查询效率 - 从表中选择 2 个最新的“组/批次”记录

用于从表中选择具有最新时间戳的行的 JOOQ 代码

根据日期参数从表中选择周末或工作日数据

从表中选择行,使其列的计算值总和小于给定限制

Google BigQuery:仅从最新表中选择