如何在非常大的 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);