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" 索引,从而获得更快的速度。
正在尝试优化 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" 索引,从而获得更快的速度。