【问题标题】: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...)

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

【问题讨论】:

    标签: sql mysql query-optimization grouping groupwise-maximum


    【解决方案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 上有一个索引。

      编辑:概括

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-16
        • 2012-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多