我有一个名为“article”的表,其中包含 1,145,141 条记录,其中包含各种字段,包括
“id”、“uiqPID”、“租户”、“状态”、“标题”、“正文”、“user_id”、“category_id”、“created_at”和“updated_at”。
“状态”列可以具有以下三个值之一:“已发布”、“草稿”或“已归档”,并具有以下计数:
我设置了以下索引:
我的问题在于以下查询的性能,该查询的执行时间为 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 秒,类似于没有此条件或具有“草稿”状态的查询?
你所经历的行为实际上是我所期望的。将 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 等,这样您就可以在等待其他结果的同时处理第一个结果,也许可以减少不耐烦的用户的挫败感。但这并不能改变加载所有这些内容需要时间的事实,即使如果显示部分结果具有一些有用的意义,您可以使等待用户变得更加友好。