如何在非常大的 MySQL table 中获取一天前每组的单个记录?
How to get a single record per group from one day ago in a very large MySQL table?
假设我有一个 table 包含各种类型的水果和蔬菜table。每 5-10 分钟一次,我检查我列出的所有项目的当前价格,并为该时间戳插入一条包含当前价格的新记录。
以下是此类 table 的示例(为了便于阅读,减少了行数,但假设每个水果每 5 分钟有一个条目):
| slug | price | time |
+--------+-------+---------------------+
| tomato | 1.5 | 2022-02-05 18:05:00 |
| tomato | 1.5 | 2022-02-05 21:05:00 |
| tomato | 1.55 | 2022-02-06 01:05:00 |
| tomato | 1.7 | 2022-02-06 08:05:00 |
| tomato | 1.65 | 2022-02-06 14:05:00 |
| tomato | 1.63 | 2022-02-07 02:05:00 |
| tomato | 1.69 | 2022-02-07 10:05:00 |
| tomato | 1.7 | 2022-02-07 18:05:00 |
| tomato | 1.49 | 2022-02-08 04:05:00 |
| tomato | 1.58 | 2022-02-08 18:05:00 |
| kiwi | 0.9 | 2022-02-05 18:05:00 |
| kiwi | 0.95 | 2022-02-05 21:05:00 |
| kiwi | 0.81 | 2022-02-06 01:05:00 |
| kiwi | 1.01 | 2022-02-06 08:05:00 |
| kiwi | 1.05 | 2022-02-06 14:05:00 |
| kiwi | 1.1 | 2022-02-07 02:05:00 |
| kiwi | 1.08 | 2022-02-07 10:05:00 |
| kiwi | 0.95 | 2022-02-07 18:05:00 |
| kiwi | 1.04 | 2022-02-08 04:05:00 |
| kiwi | 1.15 | 2022-02-08 18:05:00 |
| lemon | 1.69 | 2022-02-05 18:05:00 |
| lemon | 1.3 | 2022-02-05 21:05:00 |
| lemon | 1.35 | 2022-02-06 01:05:00 |
| lemon | 1.35 | 2022-02-06 08:05:00 |
| lemon | 1.3 | 2022-02-06 14:05:00 |
| lemon | 1.35 | 2022-02-07 02:05:00 |
| lemon | 1.41 | 2022-02-07 10:05:00 |
| lemon | 1.49 | 2022-02-07 18:05:00 |
| lemon | 1.5 | 2022-02-08 04:05:00 |
| lemon | 1.49 | 2022-02-08 18:05:00 |
现在,我想 select 我拥有的所有物品,并显示它们 24 小时前的价格。使用以下查询,我可以为每个符合“1 天前”条件的此类项目获取一个条目:
SELECT slug, price, time
FROM items
WHERE time >= NOW() - INTERVAL 1 DAY
GROUP BY slug
然而,问题是随着时间的推移,table 的大小会显着增加,而这个查询,过去需要几分之一秒,现在需要 5-10 秒(在我当前的table 我大约有 900 万条这样的记录,当然还有一些额外的列)。
是否有更优化的执行方式?
我猜你想显示....
的子弹、价格和时间
- table
中最早的一行
- 比一天前更新
- 每一个鼻涕虫。
首先,通过这个子查询得到你想要的记录的时间。
SELECT MIN(time) time, slug
FROM items
WHERE time >= NOW() - INTERVAL 24 HOUR
GROUP BY slug
然后像这样将该子查询加入您的 table。
SELECT items.slug, items.price, items.time
FROM items
JOIN (
SELECT MIN(time) time, slug
FROM items
WHERE time >= NOW() - INTERVAL 1 DAY
GROUP BY slug
) h ON items.slug = h.slug AND items.time = h.time
ORDER BY slug
此索引将帮助您快速完成此操作。服务器可以根据时间立即跳转到相关行。
ALTER TABLE CREATE INDEX timeslug (time, slug);
假设我有一个 table 包含各种类型的水果和蔬菜table。每 5-10 分钟一次,我检查我列出的所有项目的当前价格,并为该时间戳插入一条包含当前价格的新记录。
以下是此类 table 的示例(为了便于阅读,减少了行数,但假设每个水果每 5 分钟有一个条目):
| slug | price | time |
+--------+-------+---------------------+
| tomato | 1.5 | 2022-02-05 18:05:00 |
| tomato | 1.5 | 2022-02-05 21:05:00 |
| tomato | 1.55 | 2022-02-06 01:05:00 |
| tomato | 1.7 | 2022-02-06 08:05:00 |
| tomato | 1.65 | 2022-02-06 14:05:00 |
| tomato | 1.63 | 2022-02-07 02:05:00 |
| tomato | 1.69 | 2022-02-07 10:05:00 |
| tomato | 1.7 | 2022-02-07 18:05:00 |
| tomato | 1.49 | 2022-02-08 04:05:00 |
| tomato | 1.58 | 2022-02-08 18:05:00 |
| kiwi | 0.9 | 2022-02-05 18:05:00 |
| kiwi | 0.95 | 2022-02-05 21:05:00 |
| kiwi | 0.81 | 2022-02-06 01:05:00 |
| kiwi | 1.01 | 2022-02-06 08:05:00 |
| kiwi | 1.05 | 2022-02-06 14:05:00 |
| kiwi | 1.1 | 2022-02-07 02:05:00 |
| kiwi | 1.08 | 2022-02-07 10:05:00 |
| kiwi | 0.95 | 2022-02-07 18:05:00 |
| kiwi | 1.04 | 2022-02-08 04:05:00 |
| kiwi | 1.15 | 2022-02-08 18:05:00 |
| lemon | 1.69 | 2022-02-05 18:05:00 |
| lemon | 1.3 | 2022-02-05 21:05:00 |
| lemon | 1.35 | 2022-02-06 01:05:00 |
| lemon | 1.35 | 2022-02-06 08:05:00 |
| lemon | 1.3 | 2022-02-06 14:05:00 |
| lemon | 1.35 | 2022-02-07 02:05:00 |
| lemon | 1.41 | 2022-02-07 10:05:00 |
| lemon | 1.49 | 2022-02-07 18:05:00 |
| lemon | 1.5 | 2022-02-08 04:05:00 |
| lemon | 1.49 | 2022-02-08 18:05:00 |
现在,我想 select 我拥有的所有物品,并显示它们 24 小时前的价格。使用以下查询,我可以为每个符合“1 天前”条件的此类项目获取一个条目:
SELECT slug, price, time
FROM items
WHERE time >= NOW() - INTERVAL 1 DAY
GROUP BY slug
然而,问题是随着时间的推移,table 的大小会显着增加,而这个查询,过去需要几分之一秒,现在需要 5-10 秒(在我当前的table 我大约有 900 万条这样的记录,当然还有一些额外的列)。
是否有更优化的执行方式?
我猜你想显示....
-
的子弹、价格和时间
- table 中最早的一行
- 比一天前更新
- 每一个鼻涕虫。
首先,通过这个子查询得到你想要的记录的时间。
SELECT MIN(time) time, slug
FROM items
WHERE time >= NOW() - INTERVAL 24 HOUR
GROUP BY slug
然后像这样将该子查询加入您的 table。
SELECT items.slug, items.price, items.time
FROM items
JOIN (
SELECT MIN(time) time, slug
FROM items
WHERE time >= NOW() - INTERVAL 1 DAY
GROUP BY slug
) h ON items.slug = h.slug AND items.time = h.time
ORDER BY slug
此索引将帮助您快速完成此操作。服务器可以根据时间立即跳转到相关行。
ALTER TABLE CREATE INDEX timeslug (time, slug);