SQL查询执行缓慢求助:仅返回1条结果却耗时14.8秒
排查SQL查询性能问题的方向
首先,你的查询只返回1条结果却耗时近15秒,确实大概率是执行计划或索引层面的问题,我从几个实用的排查方向给你建议:
1. 先移除冗余子查询,简化SQL逻辑
你的查询里,LEFT JOIN已经通过b.ticketnumber IS NULL过滤掉了存在reminder_complete类型的记录,后面的NOT IN子查询属于重复校验逻辑,完全可以删掉。先简化SQL看看性能有没有明显变化:
SELECT a.ticketnumber FROM ticket_updates a LEFT JOIN ticket_updates b ON b.ticketnumber = a.sequence AND b.type = 'reminder_complete' WHERE b.ticketnumber IS NULL AND (a.type = 'reminder' OR a.type = 'reminder_high') AND (a.for_agent = '' OR a.for_agent = '2') AND a.notes <= '2018-05-10 23:00:00'
冗余的子查询可能会让优化器做额外的重复计算,先去掉试试。
2. 用EXPLAIN分析执行计划
执行EXPLAIN + 你的SQL,重点关注这几个关键点:
- 是否出现
ALL类型的扫描(全表扫描),大表的全表扫描是性能杀手 - 关联操作的类型,如果是
Nested Loop(嵌套循环)且关联数据量很大,会拖慢查询;可以看看是否能切换为Hash Join或Merge Join key列是否为空,为空说明没有用到索引,这是性能慢的常见原因rows列的预估扫描行数,如果和实际数据量差距过大,说明数据库统计信息过时了
3. 检查索引是否匹配查询需求
针对你的查询,建议重点优化这些字段的索引:
- 过滤条件组合:
a.type、a.for_agent、a.notes可以创建复合索引idx_type_foragent_notes (type, for_agent, notes),让过滤更快定位到目标行 - 关联条件组合:关联时需要匹配
b.type='reminder_complete'和b.ticketnumber=a.sequence,可以创建索引idx_type_ticketnumber (type, ticketnumber),或者根据数据分布调整字段顺序 - 单独给
a.sequence加索引:因为它作为关联的右值,如果经常被用于关联查询,索引能大幅减少关联时的匹配时间
4. 验证关联逻辑的合理性
你的关联条件是b.ticketnumber = a.sequence,这个逻辑是否符合业务需求?比如sequence字段是否确实存储的是其他工单的编号?如果这个关联条件会产生大量中间匹配行(哪怕最后被IS NULL过滤),会生成超大临时表拖慢查询。可以单独执行这条语句看看中间结果量:
SELECT COUNT(*) FROM ticket_updates a JOIN ticket_updates b ON b.ticketnumber = a.sequence AND b.type='reminder_complete'
如果结果行数很多,那就是这个关联逻辑导致的性能瓶颈。
5. 更新表的统计信息
如果你的表数据量很大,或者最近有大量插入/更新/删除操作,数据库的统计信息可能过时,导致优化器选择了低效的执行计划。可以执行对应命令更新统计信息:
- MySQL:
ANALYZE TABLE ticket_updates; - PostgreSQL:
ANALYZE ticket_updates;
让优化器基于最新数据选择最优执行计划。
内容的提问来源于stack exchange,提问作者charlie
相关产品推荐
相关产品推荐

