优化“已归档”状态选择的 MySQL 查询性能

问题描述 投票:0回答:1

我有一个名为“article”的表,其中包含 1,145,141 条记录,其中包含各种字段,包括

“id”、“uiqPID”、“租户”、“状态”、“标题”、“正文”、“user_id”、“category_id”、“created_at”和“updated_at”。

“状态”列可以具有以下三个值之一:“已发布”、“草稿”或“已归档”,并具有以下计数:

  • 已发表:2
  • 草稿:26,145
  • 已存档:1,118,993

我设置了以下索引:

  1. “id”上的主索引
  2. 'uiqPID'上的article_abstract_unq_id索引
  3. “租户”上的article_abstract_unq_id索引
  4. “状态”上的article_status_idx索引
  5. “id”上的 idx_composite_search 索引
  6. “uiqPID”上的 idx_composite_search 索引
  7. “created_at”上的 idx_composite_search 索引

我的问题在于以下查询的性能,该查询的执行时间为 5.7 秒:

SELECT 
    a.id AS id,
    a.created_at AS created_at
FROM 
    article a
WHERE 
    a.status = 'ARCHIVED'
ORDER BY a.created_at DESC;

但是,如果我删除 WHERE 条件或将其更改为 a.status = 'DRAFT',则查询会在 1 秒内完成。

在检查查询计划时,我注意到执行策略的差异。通过“已存档”或“草稿”状态过滤器,计划显示:

key: article_status_idx
Extra: Using index condition; Using filesort

但是如果没有“存档”过滤器,该计划只是简单地说明:

key:
Extra: Using filesort

我的问题是:如何优化查询性能以过滤“已归档”状态,确保其执行速度快于当前 5.7 秒,类似于没有此条件或具有“草稿”状态的查询?

sql mysql sqlperformance
1个回答
0
投票

你所经历的行为实际上是我所期望的。将 1,118,993 个数字时间戳元组写入内存需要时间,特别是如果您按

created_at
对结果进行排序。您需要测试以下内容:

SELECT 
    a.id AS id,
    a.created_at AS created_at
FROM 
    article a
ORDER BY a.created_at DESC
LIMIT 0, 1,118,993;

如果执行这个查询的时间与使用where子句执行查询的时间大致相同,那么导致性能下降的不是where子句,而是对查询进行排序+将结果加载到内存中。还运行以下命令:

SELECT 
    a.id AS id,
    a.created_at AS created_at
FROM 
    article a
LIMIT 0, 1,118,993;

我们这里甚至没有订单。如果这同样慢,那么你主要等待的就是将这些东西写入内存。

无论如何,进行这些测量,结果要么确认缓慢是由 where 或 order by 子句引起的,要么不是。如果这些子句导致速度缓慢,请在评论部分告诉我,我将提供优化该问题的方法。但真正的问题很可能是您正在等待执行完整的查询。

也许最好将查询分成多个分区,并以限制 0、10000 运行查询,然后限制 10000、10000 等,这样您就可以在等待其他结果的同时处理第一个结果,也许可以减少不耐烦的用户的挫败感。但这并不能改变加载所有这些内容需要时间的事实,即使如果显示部分结果具有一些有用的意义,您可以使等待用户变得更加友好。

© www.soinside.com 2019 - 2024. All rights reserved.