MySQL 查询优化 Group By with Max

MySQL Query Optimization Group By with Max

正在尝试优化 MySQL 使用 Group by 和 Max 的查询。正在尝试获取在任何过去日期之前处于活动状态的最新更新帧。

审计框架Table结构:

id bigint pk AI
frame_id bigint fk
name VARCHAR(50)
active int
createdOn DATETIME
updatedOn DATETIME
deletedOn DATETIME

id、frame_id 和 updatedOn 有单独的索引..

当前查询:

SELECT MAX(id) as id1 
  FROM audit_frame_master 
 WHERE updatedOn <='2019-03-25 21:00:00' 
   AND active=1 
   AND deletedOn IS NULL 
 GROUP 
    BY frame_id

性能:

Table 有大约 100 万行。执行平均需要 4 秒.. 有什么方法可以优化上面的查询吗?

下面是相同的 EXPLAIN 语句。

添加以下复合索引:(frame_id, active, deletedOn, updatedOn, id) 并报告其执行情况。

查询看起来不错。您所能做的就是提供适当的索引。这至少是 WHERE 子句中列的索引。从最严格的列开始。所以,

  • 有多少行匹配 active = 1
  • 有多少行匹配 deletedOn IS NULL
  • 有多少行匹配 updatedOn <= timestamp '2019-03-25 21:00:00'

选择行数最少的那个。假设是 active,然后是 updatedOn,然后是 deletedOn。这给你:

create index idx on audit_frame_master(active, updatedOn, deletedOn);

因为你想按 frame_id 分组,然后找到最大值 id,你可以按以下顺序添加:

create index idx on audit_frame_master(active, updatedOn, deletedOn, frame_id, id);

这是覆盖索引。如果 DBMS 使用它,它甚至不必访问 table.

DBMS 可能会也可能不会使用该索引。这只是一个提议。如果 DBMS 认为遍历索引而不是简单地按顺序读取 table 的工作量太大,那么它就不会使用它。试试吧。

你不想

 SELECT frame_id, MAX(id)

而不是

 SELECT           MAX(id)

??

可能这是最佳索引。注意它是如何首先列出 WHERE 列的,假设过滤比分组更重要:

INDEX(active, deletedOn,   -- in either order
      updatedOn)

frame_id, id 上添加(以任一顺序,但在最后)会将其变成 "covering" 索引,从而获得更快的速度。