通过explain查看sql的执行计划时,Extra字段的值往往会看到Using where; Using index; Using temporary; Using filesort

一、using filesort

        在使用order by关键字的时候,如果待排序的内容不能由所使用的索引直接完成排序的话,那么mysql有可能就要进行文件排序。

【这个 filesort 并不是说通过磁盘文件进行排序,而只是告诉我们进行了一个排序操作而已】。

此时,可以进行的优化:

        1、修改逻辑,不在mysql中使用order by而是在应用中自己进行排序。

        2、使用mysql索引,将待排序的内容放到索引中,直接利用索引的排序。

filesort是通过相应的排序算法,将取得的数据在内存中进行排序:。

        MySQL需要将数据在内存中进行排序,所使用的内存区域也就是我们通过sort_buffer_size 系统变量所设置的排序区。

        这个排序区是每个Thread 独享的,所以说可能在同一时刻在MySQL 中可能存在多个 sort buffer 内存区域。

在MySQL中filesort 的实现算法实际上是有两种:

        双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序。

        单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序。

        filesort使用的算法是QuickSort,即对需要排序的记录生成元数据进行分块排序,然后再使用mergesort方法合并块。其中filesort可以使用的内存空间大小为参数sort_buffer_size的值,默认为2M。当排序记录太多sort_buffer_size不够用时,mysql会使用临时文件来存放各个分块,然后各个分块排序后再多次合并分块最终全局完成排序。

二、Using temporary

        Using temporary表示由于排序没有走索引、使用union、子查询连接查询、使用某些视图等原因。因此创建了一个内部临时表。注意这里的临时表可能是内存上的临时表,也有可能是硬盘上的临时表,理所当然基于内存的临时表的时间消耗肯定要比基于硬盘的临时表的实际消耗小。

        查看sql执行时使用的是内存临时表还是硬盘临时表,需要使用如下命令:

mysql> show global status like '%tmp%';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0     |
| Created_tmp_files       | 5     |
| Created_tmp_tables      | 11    |
+-------------------------+-------+
3 rows in set

Created_tmp_tables表示mysql创建的内部临时表的总数(包括内存临时表和硬盘临时表);

Created_tmp_disk_tables表示mysql创建的硬盘临时表的总数。

        当mysql需要创建临时表时,选择内存临时表还是硬盘临时表取决于参数tmp_table_size和max_heap_table_size,内存临时表的最大容量为tmp_table_size和max_heap_table_size值的最小值,当所需临时表的容量大于两者的最小值时,mysql就会使用硬盘临时表存放数据。

用户可以在mysql的配置文件里修改该两个参数的值,两者的默认值均为16M。

tmp_table_size = 16M

max_heap_table_size = 16M

查看tmp_table_size和max_heap_table_size值:

mysql> show global variables like 'max_heap_table_size';
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| max_heap_table_size | 16777216 |
+---------------------+----------+
1 row in set

mysql> show global variables like 'tmp_table_size';
+----------------+----------+
| Variable_name  | Value    |
+----------------+----------+
| tmp_table_size | 16777216 |
+----------------+----------+
1 row in set

三、using index

        using index :使用覆盖索引的时候就会出现

四、useing where

        using where:在查找使用索引的情况下,需要回表去查询所需的数据

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐