explain出现 Using filesort ,如何优化?

关系型数据库MySQL开发与运维

大家好,我是苏三。

在对以一个 SQL 的执行计划进行分析时,我们会关注 Extra 这个属性,当这个属性的值是 Using filesort 时,就需要看下 SQL 是否需要优化一下了。

1.Using filesort

比如下面的这个 SQL,排序字段上没有索引, 执行计划 Extra 就显示 Using filesort :

  
EXPLAIN SELECT * FROM test4 ORDER BY time\_stamp;  

picture.image也可以通过 FORMAT=JSON 获取更详细的信息:

  
EXPLAIN FORMAT=JSON SELECT * FROM employees ORDER BY first\_name;  

结果如下:

  
{  
  "query\_block": {  
    "select\_id": 1,  
    "cost\_info": {  
      "query\_cost": "1034355.60"  
    },  
    "ordering\_operation": {  
      "using\_filesort": true,  
      "cost\_info": {  
        "sort\_cost": "857663.00"  
      },  
      "table": {  
        "table\_name": "test4",  
        "access\_type": "ALL",  
        "rows\_examined\_per\_scan": 857663,  
        "rows\_produced\_per\_join": 857663,  
        "filtered": "100.00",  
        "cost\_info": {  
          "read\_cost": "5160.00",  
          "eval\_cost": "171532.60",  
          "prefix\_cost": "176692.60",  
          "data\_read\_per\_join": "65M"  
        },  
        "used\_columns": [  
          "id",  
          "a",  
          "b",  
          "date",  
          "date\_time",  
          "time\_stamp"  
        ]  
      }  
    }  
  }  
}  

Using filesort 是指执行的 SQL 无法使用索引进行排序,需要在内存或磁盘上进行排序。如下图:

picture.image

所以 Using filesort 不是一定会使用磁盘排序。

那 Using filesort 对性能有哪些影响呢?

  • 排序操作需要大量 CPU,CPU 消耗很大;
  • 如果在内存中排序,排序操作会消耗很大内存;
  • 当数据无法在内存中完成排序时,就会用到磁盘临时文件,消耗磁盘 I/O。

由于 CPU、 内存或磁盘的消耗,会直接导致 SQL 性能下降,执行时间长。

2.原因分析

2.1 ORDER BY 未走索引

这是最常见的原因,主要包括以下几种情况:

  • ORDER BY 字段未加索引;
  • ORDER BY 语句中字段排序顺序跟索引顺序不一致;
  • 有复合索引,但 ORDER BY 语句中的列不符合最左前缀原则;
  • ORDER BY 语句中使用了表达式或函数。

上面这些情况都可能走 filesort。

2.2 JOIN 语句

  
SELECT * FROM t1 JOIN t2 ON t1.c1=t2.c1 order by t2.c2;  

MySQL 会选择结果集较小的表作为驱动表,比如上面的 SQL,两张表使用 c1 这个字段进行 JOIN,如果选择了 t1 做为驱动表,但是使用 t2 的字段 c2 进行排序,那排序操作就会走不上索引。

2.3 UNION 语句

  
EXPLAIN SELECT id,a,b FROM test4 UNION SELECT * FROM test5 ORDER BY a;  

在 union 语句中,如果对结果集进行排序,也有可能会走 filesort。

2.4 GROUP BY

  
SELECT age,COUNT(age) ca FROM db\_staff GROUP BY age;  

上面是一个分组的 SQL,在 MySQL 8.0 以前,GROUP BY 默认是会对分组字段做排序的,即使 sql 中没写 ORDER BY,也会排序。如果分组字段未加索引,很容易走 filesort

如果想要 sql 语句不排序,可以在 sql 尾部加 order by null。

2.5 DISTINCT 语句

  
EXPLAIN SELECT DISTINCT b FROM test5 ORDER BY b;  

如果在 DISTINCT 语句中使用 ORDER BY,可能会走 filesort。

2.6 临时表

当查询需要创建临时表,比如上面的 UNION、DISTINCT 和 GROUP BY,如果临时表结果集需要排序,则可能使用 filesort。

3.优化思路

3.1 索引优化

如果 ORDER BY 字段没能走索引,可以考虑进行优化:

  • ORDER BY 只有一个字段,则为该字段增加索引;
  • ORDER BY 有多个字段,可以考虑复合索引。比如下面的示例:
  
CREATE INDEX idx\_a\_b ON orders(a, b);  
  
EXPLAIN SELECT * FROM test4 WHERE a = 'testa' ORDER BY b;  

  • 排除可能使索引失效的情况,比如函数或表达式、ORDER BY 和索引 顺序不一致;
  • 没有必要排序的场景,可以不排序,比如使用 ORDER BY NULL 语句。

JOIN 优化

确保 ORDER BY 子句的字段是驱动表上的索引字段,并且符合最左前缀原则,必要时可以强制使用索引 FORCE INDEX。

配置优化

增大 sort_buffer_size 配置,避免走磁盘排序。不过一定要注意,sort buffer 是会话私有的,高并发场景下,可能导致数据库内存升高。

4.总结

当执行计划的 Extra 属性出现 Using filesort 时,大概率我们的 SQL 需要优化了。可能查看 SQL 属于那种情况,针对性地进行优化。

最后欢迎加入苏三的星球,你将获得:苏三商城系统、智能天气播报AI Agent、SaaS点餐系统(DDD+多租户)、100万QPS短链系统(超过并发)、复杂的商城微服务系统(分布式)、苏三AI项目、刷题吧小程序、秒杀系统、码猿简历网站、代码生成工具等10个项目的源代码、开发教程和技术答疑。 系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1免费修改简历、技术答疑、职业规划、送书活动、技术交流。

扫描下方二维码,可以加入星球:

picture.image

数量有限,先到先得。 目前星球已经更新了6100+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有2100+小伙伴加入学习。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动 NoSQL 的实践与探索
随着 NoSQL 的蓬勃发展越来越多的数据存储在了 NoSQL 系统中,并且 NoSQL 和 RDBMS 的界限越来越模糊,各种不同的专用 NoSQL 系统不停涌现,各具特色,形态不一。本次主要分享字节跳动内部和火山引擎 NoSQL 的实践,希望能够给大家一定的启发。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论