MySQL查询优化求助:添加索引后仍耗时2.6秒
MySQL查询优化建议
问题分析
你的查询耗时2.6秒,移除ORDER BY后性能大幅提升,说明排序操作(filesort)是核心性能瓶颈。当前添加的索引未针对排序和过滤条件做优化,导致MySQL需要先扫描大量数据、再排序,最后分页,效率极低。
具体优化步骤
1. 清理无效过滤条件
查询中存在大量恒成立的无效条件,会干扰优化器判断,直接删除即可:
- 移除
(null is null or posummary0_.created_at >= null)这类无意义的条件 - 移除
('%%' is null or '%%' = '' or postatus4_.code like '%')这类全匹配的冗余条件 - 移除其他类似
null is null的恒真判断
清理后的查询过滤条件会更简洁,优化器能更精准地选择执行计划。
2. 创建针对排序的复合覆盖索引
核心问题是ORDER BY posummary0_.created_at desc需要全量排序,为此给po_summaries表创建复合索引,覆盖过滤条件+排序字段:
CREATE INDEX idx_po_summary_active_created ON po_summaries (is_active, created_at DESC);
如果后续业务中会用到po_number、created_at范围等过滤条件,可以扩展索引进一步覆盖:
CREATE INDEX idx_po_summary_filter_sort ON po_summaries (is_active, created_at DESC, po_number);
该索引能让MySQL直接从索引中获取有序数据,避免全量filesort,同时快速过滤is_active=1的数据,大幅提升分页效率。
3. 检查关联表索引
确保关联字段存在有效索引:
po_payments.po_summary_id:作为左连接的关联字段,必须创建索引,否则会导致全表扫描关联sku_farmers.id、warehouses.id、po_status.id:这些是主键,默认已有索引,无需额外操作;如果后续用uuid做过滤,可给对应字段加索引
4. 优化JOIN写法
将cross join改为inner join,逻辑等价但可读性更强,优化器执行计划不受影响:
from po_summaries posummary0_ left outer join po_payments popayment1_ on posummary0_.id = popayment1_.po_summary_id inner join sku_farmers farmer2_ on posummary0_.sku_farmer_id = farmer2_.id inner join warehouses warehouse3_ on posummary0_.warehouse_id = warehouse3_.id inner join po_status postatus4_ on posummary0_.po_status_id = postatus4_.id
5. 验证优化效果
执行EXPLAIN查看执行计划:
- 确认
Extra列中无Using filesort,说明排序已使用索引 - 确认
type列显示range或ref,而非ALL(全表扫描)
总结
核心优化点是通过复合索引消除排序瓶颈,同时清理冗余条件、优化关联写法,确保MySQL能高效利用索引完成查询。
内容的提问来源于stack exchange,提问作者Amimul Ehsan Rahi
相关产品推荐
相关产品推荐

