Using temporary和Using filesort分析

mysql> show create table t1;
+-------+----------------------------------
| Table | Create Table                                            
+-------+--------------------------------
| t1    | CREATE TABLE `t1` (
 `id` int(11) NOT NULL DEFAULT ‘0‘,
 `age` int(11) DEFAULT NULL,
 `name` varchar(32) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `age_1` (`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+---------------------------------
1 row in set (0.00 sec)

1 测试order by使用索引的情况
#按主键id进行排序,走的是主键索引。主键索引b+tree,叶子节点(存储的是行数据)是按照主键索引顺序组织的。
mysql> desc select * from t1 order by id;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
|  1 | SIMPLE      | t1    | index | NULL          | PRIMARY | 4       | NULL |    9 | NULL  |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
1 row in set (0.00 sec)

#按普通索引age排序,走的是全表扫描。他之所以没有走普通索引,是因为如果用filesort排序代价更小。
如果走普通索引,先走二级索引b+tree,找到对应的主键key;再走主键索引数,找到叶子节点主键值对应的行记录。
mysql> desc select * from t1 order by age;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
不让查询优化器自己选择,强制使用索引。
mysql> desc select * from t1 force index(age) order by age;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
|  1 | SIMPLE      | t1    | index | NULL          | age_1 | 5       | NULL |    9 | NULL  |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
1 row in set (0.00 sec)
#不使用索引的字段排序
mysql> desc select * from t1 order by name;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
=========================================================================
如果select column 里面的column加了索引,不需要回表, 直接using index。
#查询id字段,id是主键,useing index,不回表。
mysql> desc select id from t1 order by age;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age_1 | 5       | NULL |    9 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
1 row in set (0.00 sec)

#查询age字段,普通索引,useing index,不回表。
mysql> desc select age from t1 order by age;  
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | t1    | index | NULL          | age_1 | 5       | NULL |    9 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
1 row in set (0.00 sec)
=========================================================================
2 group by 测试
mysql> desc select * from t1 group by id;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
|  1 | SIMPLE      | t1    | index | PRIMARY,age_1 | PRIMARY | 4       | NULL |    9 | NULL  |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> desc select * from t1 group by age;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
|  1 | SIMPLE      | t1    | index | age_1         | age_1 | 5       | NULL |    9 | NULL  |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------+
1 row in set (0.00 sec)

#如果排序字段没有索引,则extra 会出现 Using temporary; Using filesort

#默认group by 会自动按照by后边的字段进行排序,这样增加了系统消耗,可以取消默认排序。见下边实验
mysql> desc select * from t1 group by name ;
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                           |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
1 row in set (0.00 sec)
mysql> desc select * from t1 group by name order by null;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra           |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------+
|  1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using temporary |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------+
1 row in set (0.00 sec)

#未去掉默认排序
mysql>  select * from t1 group by name;
+----+------+--------+
| id | age  | name   |
+----+------+--------+
|  7 |    0 | aaaa   |
|  1 |    0 | kenney |
|  5 |    0 | tttt   |
+----+------+--------+
3 rows in set (0.00 sec)

#去掉默认排序后
mysql>  select * from t1 group by name order by null;    
+----+------+--------+
| id | age  | name   |
+----+------+--------+
|  1 |    0 | kenney |
|  5 |    0 | tttt   |
|  7 |    0 | aaaa   |
+----+------+--------+
3 rows in set (0.00 sec)

备注:
尽量按索引键进行排序,这样效率会很高。 
我们还会发现,在排序的语句中都出现了Using filesort,字面意思可能会被理解为:使用文件进行排序或中文件中进行排序。实际上这是不正确的,这是一个让人产生误解的词语。 
当我们试图对一个没有索引的字段进行排序时,就是filesoft。它跟文件没有任何关系,实际上是内部的一个快速排序。

执行计划关键字解析:
extra字段中
Using filesort
MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
Using index
从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
Using temporary
为了解决查询,MySQL需要创建一个临时表来容纳结果。

type字段中
ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取
ALL
完全没有索引的情况,性能非常地差劲。
index
与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
时间: 2024-08-26 04:41:34

Using temporary和Using filesort分析的相关文章

转载(MySQL Order By实现原理分析和Filesort优化)

在MySQL中的ORDER BY有两种排序实现方式: 1.利用有序索引获取有序数据 2.文件排序 在使用explain分析查询的时候,利用有序索引获取有序数据显示Using index.而文件排序显示Using filesort. 1.利用有序索引获取有序数据 取出满足过滤条件作为排序条件的字段,以及可以直接定位到行数据的行指针信息,在 Sort Buffer 中进行实际的排序操作,然后利用排好序的数据根据行指针信息返回表中取得客户端请求的其他字段的数据,再返回给客户端. 这种方式,在使用exp

MySQL索引题目分析

1.之前看视频呢的时候,里面提到一道索引题目:假设某个表有一个联合索引(c1,c2,c3,c4)-只能使用该联合索引的c1,c2,c3部分 a.where c1=x and c2=x and c4>x and c3=x b.where c1=x and c2=x and c4=x order by c3 c.where c1=x and c4=x group by c3,c2 d.where c1=? and c5=? order by c2,c3 e.where c1=? and c2=? a

MySQL与OLAP:分析型SQL查询最佳实践探索

搞点多维分析,糙快猛的解决方案就是使用ROLAP(关系型OLAP)了.数据经维度建模后存储在MySQL,ROLAP引擎(比如开源的Mondrian)负责将OLAP请求转化为SQL语句提交给数据库.OLAP计算分析功能导致MySQL需要进行较多复杂SQL查询,性能调优必不可少,本文总结了一些实用原则. OLAP特点 OLAP的典型应用包括复杂动态报表,需要支持钻取(上卷和下钻).切片.切块和旋转操作.下表总结了OLAP和OLTP系统的主要区别.OLAP的特点决定了SQL的查询场景和优化方案,下文将

MySQL 语句分析及sql进程查看

在 my.cnf 文件中配置好:slow_query_log=1slow_query_log_file=mysql.slowlong_query_time=10即可记录超过默认的 10s 执行时间的 SQL 语句.如果要修改默认设置,可以添加:long_query_time = 5设定为 5s . MySQL 自带 slow log 的分析工具 mysqldumpslow.slow log 是 MySQL 根据 SQL 语句的执行时间设定,写入的一个文件,用于分析执行较慢的语句. explain

MySQL的explain分析sql语句

explain分析查询 使用 EXPLAIN 关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的.这可以帮你分析你的查询语句或是表结构的性能瓶颈.通过explain命令可以得到: 表的读取顺序 数据读取操作的操作类型 哪些索引可以使用 哪些索引被实际使用 表之间的引用 每张表有多少行被优化器查询 如下为实验表格:里面有1万条测试数据 EXPLAIN字段解析: 1.table:显示这一行的数据是关于哪张表的 2.type:这是最重要的字段之一,显示查询使用了何种类

MySQL高级知识(七)——索引面试题分析

前言:该篇随笔通过一些案例,对索引相关的面试题进行分析. 0.准备 #1.创建test表(测试表). drop table if exists test; create table test( id int primary key auto_increment, c1 varchar(10), c2 varchar(10), c3 varchar(10), c4 varchar(10), c5 varchar(10) ) ENGINE=INNODB default CHARSET=utf8; i

MySQL中如何查看“慢查询”,如何分析执行SQL的效率?

一.MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句 1,slow_query_log这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句. 2,long_query_time当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短. 3,slow_query_log_file记录日志的文件名. 4,log_queries_not_using_indexes这个参数设置为ON,可以捕获到所有未使用索引的SQL语句,尽管这个SQL语句有可能执行得挺快. 二

【MySQL 原理分析】之 Trace 分析 order by 的索引原理

一.背景 昨天早上,交流群有一位同学提出了一个问题.看下图: 我不是大佬,而且当时我自己的想法也只是猜测,所以并没有回复那位同学,只是接下来自己做了一个测试验证一下. 他只简单了说了一句话,就是同样的sql,一个没加 order by 就全表扫描,一个加了 order by 就走索引了. 我们可以仔细点看一下他提供的图(主要分析子查询即可,就是关于表 B 的查询,因为只有表 B 的查询前后不一致),我们可以先得出两个前提: 1.首先可以肯定的是,where 条件中的 mobile 字段是没有索引

MySQL STRAIGHT_JOIN

问题 最近在调试一条查询耗时5s多的sql语句,这条sql语句用到了多表关联(inner join),按时间字段排序(order by),时间字段上已经创建了索引(索引名IDX_published_at).通过explain分析发现,时间字段上的索引没用上(Using temporary和Using filesort),问题很明显,但是原因是什么呢? SELECT * FROM news n0_ inner join news_translations n1_ ON n0_.id = n1_.t