【问题标题】:Optimize correlated subquery for order events table优化订单事件表的关联子查询
【发布时间】:2022-01-20 07:42:11
【问题描述】:

我有一个包含订单事件的 MariaDB 表:

EVENTID ORDERID DATA TIMESTAMP
1 1 'stuff1' 2021-12-17 11:48:00.000
2 1 'newstuff1' 2021-12-17 11:49:00.000
3 1 'newerstuff1' 2021-12-17 11:49:30.000
4 2 'stuff2' 2021-12-17 11:50:00.000
5 3 'stuff3' 2021-12-17 11:51:10.000
6 3 'newstuff3' 2021-12-17 11:52:00.000

我需要获取每个订单的最新事件。 所以对于这个数据集,结果应该是

EVENTID ORDERID DATA TIMESTAMP
3 1 'newerstuff1' 2021-12-17 11:49:30.000
4 2 'stuff2' 2021-12-17 11:50:00.000
6 3 'newstuff3' 2021-12-17 11:52:00.000

我正在使用相关子查询来实现这一点:

SELECT *
FROM MESSAGES m1
WHERE TIMESTAMP = (SELECT MAX(TIMESTAMP) 
FROM MESSAGES m2 WHERE m1.ORDERID = m2.ORDERID);

但是对于大容量来说这很慢,所以我想知道是否有一种方法可以使用连接或分组来改进查询。否则,如果有帮助,我愿意将数据拆分到不同的表中。

【问题讨论】:

  • 什么版本的玛丽亚?

标签: mysql mariadb subquery groupwise-maximum


【解决方案1】:
SELECT m3.*
    FROM ( SELECT ORDERID, MAX(TIMESTAMP) AS TIMESTAMP
              FROM MESSAGES m1
              GROUP BY ORDERID ) m2
    JOIN MESSAGES m3 USING(ORDERID, TIMESTAMP);

并且拥有

INDEX(ORDERID, TIMESTAMP)

查询是“groupwise-max”模式。

派生表(子查询)将跳过索引,然后从表中查找其余列。

如果给定订单 ID 有任何重复的时间戳,它将交付多行。如果不需要,请参阅this 了解更多选项。

【讨论】:

    【解决方案2】:
    SELECT *
    FROM table t1
    WHERE NOT EXISTS ( SELECT NULL
                       FROM table t2
                       WHERE t1.orderid = t2.orderid
                         AND t1.`timestamp` < t2.`timestamp` )
    

    即如果没有具有相同订单 ID 且日期更近的另一行,则只需选择该行。

    附言。 (orderid, `timestamp`) 的索引会有所改善。

    【讨论】:

    • 谢谢,这行得通,但它实际上比我最初的查询慢,至少在我的测试中。
    猜你喜欢
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多