【发布时间】:2023-04-11 00:58:02
【问题描述】:
我想从历史记录表中检索项目的最新状态。历史表将记录一个项目的所有状态变化。查询必须快速运行。
以下是我用来获取每个项目的最新状态的查询
SELECT item_history.*
FROM item_history
INNER JOIN (
SELECT MAX(created_at) as created_at, item_id
FROM item_history
GROUP BY item_id
) as latest_status
on latest_status.item_id = item_history.item_id
and latest_status.created_at = item_history.created_at
WHERE item_history.status_id = 1
and item_history.created_at BETWEEN "2020-12-16" AND "2020-12-23"
我已经尝试将上面的查询放入另一个内部联接中以将数据与项目链接:
SELECT *
FROM `items`
INNER JOIN ( [query from above] )
WHERE items.category_id = 3
备注关于 item_history 表,我在以下列上有索引:status_id、creatd_at 和 Listing_id。我还把其中的 3 个变成了复合主键。
我的问题是 MySQL 一直在扫描整个表以获取 MAX(created_at),这是一个非常慢的操作,即使我在历史表中只有 300 万条记录。
查询计划如下:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | PRIMARY | items | NULL | ref | "PRIMARY,district" | district | 18 | const | 694 | 100.00 | NULL |
| 1 | PRIMARY | item_history | NULL | ref | "PRIMARY,status_id,created_at,item_history_item_id_index" | PRIMARY | 9 | "main.items.id,const" | 1 | 100.00 | "Using where" |
| 1 | PRIMARY | NULL | ref | <auto_key0> | <auto_key0> | 14 | "func,main.items.id" | 10 | 100.00 | "Using where; Using index" | |
| 2 | DERIVED | item_history | NULL | range | "PRIMARY,status_id,created_at,item_history_item_id_index" | item_history_item_id_index | 8 | NULL | 2751323 | 100.00 | "Using index" |
【问题讨论】:
-
最佳“groupwise-max”代码在这里:mysql.rjweb.org/doc.php/groupwise_max
-
@RickJames 你一如既往的棒!感谢您撰写所有这些文章 - 它们非常有用。
-
这是一个有趣的挑战。
标签: mysql sql datetime query-optimization greatest-n-per-group