explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。使用方法,在select语句前加上explain就可以了.

一、explain列的解释

1、id :SELECT识别符。这是SELECT查询序列号。这个不重要,查询序号即为sql语句执行的顺序;

2、select类型,它有以下几种值

  2.1 simple 它表示简单的select,没有union和子查询

  2.2 primary 最外面的select,在有子查询的语句中,最外面的select查询就是primary

  2.3 union union语句的第二个或者说是后面那一个.

3、table:显示这一行的数据是关于哪张表的

4、type:重要,连接类型。从最好到最差的连接类型介绍如下:

  4.1 system 表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计;

  4.2 const 表最多有一个匹配行,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快记住一定是用到primary key 或者unique,并且只检索出两条数据的情况下才会是const.

举例:

explain SELECT * FROM `asj_admin_log` limit 1,结果是

虽然只搜索一条数据,但是因为没有用到指定的索引,所以不会使用const.继续看下面这个

explain SELECT * FROM `asj_admin_log` where log_id = 111

log_id是主键,所以使用了const。所以说可以理解为const是最优化的;

  4.3 eq_ref 对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。 eq_ref可以用于使用=比较带索引的列。看下面的语句

explain select * from uchome_spacefield,uchome_space where uchome_spacefield.uid = uchome_space.uid

得到的结果是下图所示。很明显,mysql使用eq_ref联接来处理uchome_space表。

目前的疑问:

4.3.1 为什么是只有uchome_space一个表用到了eq_ref,并且sql语句如果变成

explain select * from uchome_space,uchome_spacefield where uchome_space.uid = uchome_spacefield.uid

结果还是一样,需要说明的是uid在这两个表中都是primary

  4.4 ref 对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

看下面这条语句 explain select * from uchome_space where uchome_space.friendnum = 0,得到结果如下,这条语句能搜出1w条数据

  4.5 ref_or_null 该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

上面这五种情况都是很理想的索引使用情况

  

  4.6 index_merge 该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

  4.7 unique_subquery

  4.8 index_subquery

  4.9 range 给定范围内的检索,使用一个索引来检查行。看下面两条语句

explain select * from uchome_space where uid in (1,2)

explain select * from uchome_space where groupid in (1,2)

uid有索引,groupid没有索引,结果是第一条语句的联接类型是range,第二个是ALL.以为是一定范围所以说像 between也可以这种联接,很明显

explain select * from uchome_space where friendnum = 17

这样的语句是不会使用range的,它会使用更好的联接类型就是上面介绍的ref

  4.10 index     该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)

当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

  4.11  ALL  对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。

  5、possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从where语句中选择一个合适的语句。 提示使用哪个索引会在该表中找到行,不太重要

  6、key: 实际使用的索引。如果为null,则没有使用索引。很少的情况下,mysql会选择优化不足的索引。这种情况下,可以在select语句中使用use index(indexname)来强制使用一个索引或者用ignore index(indexname)来强制mysql忽略索引

  7、key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好

  8、ref:ref列显示使用哪个列或常数与key一起从表中选择行

  9、rows:显示执行查询的行数,简单且重要,数值越大越不好,说明没有用好索引

  10、extra:关于mysql如何解析查询的额外信息。

    10.1 Distinct  一旦mysql找到了与行相联合匹配的行,就不再搜索了。

    10.2 Not exists  mysql优化了left join,一旦它找到了匹配left join标准的行,就不再搜索了

    10.3 range checked for each record 没有找到合适的索引  没有找到理想的索引,因此对于从前面表中来的每一个行组合,mysql检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

    10.4 using filesort    看到这个的时候,查询就需要优化了。mysql需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行

    10.5 using index 只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的信息。这个比较容易理解,就是说明是否使用了索引

explain select * from ucspace_uchome where uid = 1的extra为using index(uid建有索引)

explain select count(*) from uchome_space where groupid=1 的extra为using where(groupid未建立索引)

    10.6 using temporary  看到这个的时候,查询需要优化了。这里,mysql需要创建一个临时表来存储结果,这通常发生在对不同的列集进行order by上,而不是group by上where used 使用了where从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型all或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)

典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时。出现using temporary就说明语句需要优化了,举个例子来说

EXPLAIN SELECT ads.id FROM ads, city WHERE   city.city_id = 8005   AND ads.status = 'online'   AND city.ads_id=ads.id ORDER BY ads.id desc

id  select_type  table   type    possible_keys   key      key_len  ref                     rows  filtered  Extra                          
------  -----------  ------  ------  --------------  -------  -------  --------------------  ------  --------  -------------------------------
     1  SIMPLE       city    ref     ads_id,city_id  city_id  4        const                   2838    100.00  Using temporary; Using filesort
     1  SIMPLE       ads     eq_ref  PRIMARY         PRIMARY  4        city.ads_id       1    100.00  Using where    

这条语句会使用using temporary,而下面这条语句则不会

EXPLAIN SELECT ads.id FROM ads, city WHERE   city.city_id = 8005   AND ads.status = 'online'   AND city.ads_id=ads.id ORDER BY city.ads_id desc

id  select_type  table   type    possible_keys   key      key_len  ref                     rows  filtered  Extra                      
------  -----------  ------  ------  --------------  -------  -------  --------------------  ------  --------  ---------------------------
     1  SIMPLE       city    ref     ads_id,city_id  city_id  4        const                   2838    100.00  Using where; Using filesort
     1  SIMPLE       ads    eq_ref  PRIMARY         PRIMARY  4        city.ads_id       1    100.00  Using where    

这是为什么呢?他俩之间只是一个order by不同,MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。EXPLAIN 结果中,第一行出现的表就是驱动表(Important!)以上两个查询语句,驱动表都是 city,如上面的执行计划所示!

对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序(Important!)
因此,order by ads.id desc 时,就要先 using temporary 了!
驱动表的定义:当进行多表连接查询时, [驱动表] 的定义为:
1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];
2)未指定联接条件时,行数少的表为[驱动表](Important!)。

永远用小结果集驱动大结果集

今天学到了一个很重要的一点:当不确定是用哪种类型的join时,让mysql优化器自动去判断,我们只需写select * from t1,t2 where t1.field = t2.field

  10.7 using where   WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。(这个说明不是很理解,因为很多很多语句都会有where条件,而type为all或index只能说明检索的数据多,并不能说明错误,useing where不是很重要,但是很常见)

如果想要使查询尽可能快,应找出Using filesort 和Using temporary的Extra值。

  10.8 Using sort_union(...), Using union(...),Using intersect(...)  这些函数说明如何为index_merge联接类型合并索引扫描

  10.9 Using index for group-by  类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。并且,按最有效的方式使用索引,以便对于每个组,只读取少量索引条目。

MYSQL数据库性能调优之三:explain分析慢查询的更多相关文章

  1. MYSQL数据库性能调优之四:解决慢查询--索引

    为什么索引能够提高查询速度?没有索引 检索数据的方式是从头到尾一条一条挨着匹配,这是慢的根本原因:索引类型BTREE:二叉树类型,原理图如下:对表创建一个二叉树,记录中间数据的物理磁盘地址,二叉树检索 ...

  2. MYSQL数据库性能调优之五:解决慢查询--存储引擎与数据类型

    3.数据类型的影响 4.存储引擎的影响 看你的mysql现在已提供什么存储引擎:mysql> show engines; 看你的mysql当前默认的存储引擎:mysql> show var ...

  3. MySQL 数据库性能调优

    MySQL 数据库性能调优 MySQL性能 最大数据量 最大并发数 优化的范围有哪些 存储.主机和操作系统方面: 应用程序方面: 数据库优化方面: 优化维度 数据库优化维度有四个: 优化选择: 数据库 ...

  4. mysql数据库性能调优总结积累

    mysql数据库的调优大概可以分为四大块 0 架构调优 ---根据业务 读写分库分表   ---主从 读写分离 1 配置的调优 ---开启缓存查询  设置缓存大小 ---最大连接数设置 ---数据库引 ...

  5. MYSQL数据库性能调优之八:mysql日志

    MySQL日志 主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志.中继日志: 使用 SHOW GLOBAL VARIABLES LIKE '%log%';  查询所有日志配置详情: 一. ...

  6. MYSQL数据库性能调优之一:调优技术基础

    1.mysql数据库优化技术有哪些? 2.数据库三层结构? 3.数据库3NF

  7. MYSQL数据库性能调优之七:其他(读写分离、分表等)

    一.分表 水平划分 垂直划分 二.读写分离 三.选择合理的数据类型 特别是主键 四.文件.图片等大文件使用文件系统存储 五.数据库参数配置 注意:max_connections最大连接数一般设置在10 ...

  8. MYSQL数据库性能调优之二:定位慢查询

    windows下开启慢查询: 第一步:先查看版本 第二步查看查询日志和慢查询配置 第三步:配置开启慢查询 在my.ini配置文件的[mysqld]选项下增加: slow_query_log=TRUE ...

  9. MYSQL数据库性能调优之六:备份

    增量备份

随机推荐

  1. IntelliJ IDEA创建第一个Java小程序

    我尝试了汉化,会影响IDE部分功能. 其实IDE完全没必要汉化,就那么几个单词,不懂的话,就有道字典查一下吧. 汉化易于入门,不汉化一样可以使用. 我爱这个编辑器,非常之强大,就是比较占内存. 我爱这 ...

  2. UML类图几种关系的总结,泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖

    在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Compositi ...

  3. hdu3333(线段树)

    区间更新,单点查询. hdu3333 #include <iostream> #include <stdio.h> #include <string.h> #inc ...

  4. 如何使页面滚动条移动到指定元素element的位置处?

    如何使页面滚动条移动到指定元素element的位置处? 在用selenium做测试时,会遇到需要操作的元素不在当前可视页面中的情况,如果是手工测试,自然很简单,手动拖拽滚动条到目标元素处即可. 那么, ...

  5. Kafka Topic动态迁移 (源代码解析)

    总结下自己在尝试Kafka分区迁移过程中对这部分知识的理解,请路过高手指正. 关于Kafka数据迁移的具体步骤指导,请参考如下链接:http://www.cnblogs.com/dycg/p/3922 ...

  6. 自己实现字符串操作函数strlen(),strcat(),strcpy(),strcmp()

    1.strlen()函数是求解字符串的有效长度的 1)非递归实现 size_t my_strlen(const char *str) { assert(str != NULL);  //断言,保证指针 ...

  7. 阿里云linux服务器安装Phalcon-----"phalcon Volt directory can't be written" "gcc: internal compiler error: Killed (program cc1)"

    这里特别蛋疼的一件事是官方英文文档和中文文档命令参数略有不同 中文文档: //通用平台下安装指定的软件包: sudo yum install git gcc make pcre-devel php-d ...

  8. a标签包input引起的问题

    最近公司中的一个项目中,有一个同事跟我说,他写的输入框不能选中输入内容了,并且光标也不能插入到已写好的文字其他位置. 简化了一下他的代码结构,如下: <a href="javascri ...

  9. liux环境下配置jdk

    大家都知道,现在JAVA的发展可谓是如日中天,它覆盖面非常广泛,小到个人PC,大到商业应用都能见到它的身影.以前它是由SUN公司来维护的,现在已经归属到甲骨文旗下了. 今天我们来学习一下Java JD ...

  10. 获取Request请求的路径信息

    从Request对象中可以获取各种路径信息,以下例子: 假设请求的页面是index.jsp,项目是WebDemo,则在index.jsp中获取有关request对象的各种路径信息如下 String p ...