mysql索引篇explain命令详解


当前第2页 返回上一页

出现于where操作符为‘=’,且where字段为非唯一索引的单表查询或联表查询。

// 单表
mysql> explain select * from dept_emp where dept_no = 'd005';
+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+
| id | select_type | table    | type | possible_keys | key     | key_len | ref   | rows   | Extra                 |
+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+
|  1 | SIMPLE      | dept_emp | ref  | dept_no       | dept_no | 4       | const | 145708 | Using index condition |
+----+-------------+----------+------+---------------+---------+---------+-------+--------+-----------------------+

// 联表
mysql> explain select * from dept_emp,departments where dept_emp.dept_no = departments.dept_no;
+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+
| id | select_type | table       | type  | possible_keys | key       | key_len | ref                           | rows | Extra       |
+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+
|  1 | SIMPLE      | departments | index | PRIMARY       | dept_name | 42      | NULL                          |    9 | Using index |
|  1 | SIMPLE      | dept_emp    | ref   | dept_no       | dept_no   | 4       | employees.departments.dept_no |    1 | NULL        |
+----+-------------+-------------+-------+---------------+-----------+---------+-------------------------------+------+-------------+

eq_ref:

出现于where操作符为‘=’,且where字段为唯一索引联表查询

mysql> explain select * from departments,dept_desc where departments.dept_name=dept_desc.dept_name;
+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+
| id | select_type | table       | type   | possible_keys | key       | key_len | ref                           | rows | Extra       |
+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+
|  1 | SIMPLE      | dept_desc   | ALL    | NULL          | NULL      | NULL    | NULL                          |    1 | NULL        |
|  1 | SIMPLE      | departments | eq_ref | dept_name     | dept_name | 42      | employees.dept_desc.dept_name |    1 | Using index |
+----+-------------+-------------+--------+---------------+-----------+---------+-------------------------------+------+-------------+

const:

出现于where操作符为‘=’,且where字段为唯一索引单表查询,此时最多只会匹配到一行。

mysql> explain select * from departments where dept_no = 'd005';
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table       | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | departments | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------+

综上,单从type字段考虑效率,const > eq_ref > ref > range > index > all.

注意:我们不能仅仅根据type去判断两条sql的执行速度。例如type为range的查询不一定比type为index的全表查询速度要快,还要看具体的sql。因为type为index时,查询是不需要回表操作的,而type为range时,有可能需要回表操作。如sqlA("select dept_no from dept_emp;")和sqlB("select from_date from dept_emp where dept_no > 'd005';"),这个时候sqlB根据where条件扫描索引树后,需要回表查询相应的行数据,以获取from_date的值,而sqlA虽然扫描了整颗索引树,但并不需要回表,所以速度可能会比sqlB更快。

回表操作、索引相关可以阅读mysql索引(覆盖索引,联合索引,索引下推)这篇文章

Extra

extra列会包含一些十分重要的信息,我们可以根据这些信息进行sql优化

  • using index: sql语句没有where查询条件,使用覆盖索引,不需要回表查询即可拿到结果
  • using where: 没有使用索引/使用了索引但需要回表查询且没有使用到下推索引
  • using index && useing where: sql语句有where查询条件,且使用覆盖索引,不需要回表查询即可拿到结果。
  • Using index condition:使用索引查询,sql语句的where子句查询条件字段均为同一索引字段,且开启索引下推功能,需要回表查询即可拿到结果。
  • Using index condition && using where:使用索引查询,sql语句的where子句查询条件字段存在非同一索引字段,且开启索引下推功能,需要回表查询即可拿到结果。
  • using filesort: 当语句中存在order by时,且orderby字段不是索引,这个时候mysql无法利用索引进行排序,只能用排序算法重新进行排序,会额外消耗资源。
  • Using temporary:建立了临时表来保存中间结果,查询完成之后又要把临时表删除。会很影响性能,需尽快优化。

下推索引、覆盖索引相关介绍可阅读mysql索引(覆盖索引,联合索引,索引下推)这篇文章

有时在extra字段中会出现"Impossible WHERE noticed after reading const tables"这种描述。翻看网上资料后,个人发现这是mysql一种很怪的处理方式。

当sql语句满足:

  • 1、根据主键查询或者唯一性索引查询;
  • 2、where操作符为"="时。

在sql语句优化阶段,mysql会先根据查询条件找到相关记录,这样,如果这条数据不存在,实际上就进行了一次全扫描,然后得出一个结论,该数据不在表中。这样对于并发较高的数据库,会加大负载。所以,如果数据不用唯一的话,普通的索引比唯一索引更好用。(文章链接:MySQL慢查询现象解决案例)

到此这篇关于mysql索引篇explain命令详解的文章就介绍到这了,更多相关mysql explain命令内容请搜索

更多相关Mysql内容来自木庄网络博客


标签:Mysql

返回前面的内容

相关阅读 >>

如何让mysql中单句实现无限层次父子关系查询

如何解决mysql 1075错误

如何向mysql数据库或者oracle或导入表格文件

mysql数据库锁机制的介绍

mysql怎么取消外键限制(约束)?

mysql数据库如何导入dbf格式数据?

我所理解的mysql之四:事务、隔离级别及mvcc

mysql怎么指定存储引擎?

mysql利用子查询效率怎么样

mysql输入错误如何不退出

更多相关阅读请进入《mysql》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...