Mysql优化之explain!

一、explain是什么?
1、 定义
EXPLAIN是mysql中的一个命令,可以模拟优化器执行SQL语句并返回执行计划。通过执行计划,我们可以分析查询语句或表结构的性能瓶颈,从而进行SQL优化。
2、用法

mysql> explain select * from employee;
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | employee | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

通过上面的执行计划我们可以了解:表的执行顺序数据读取操作的操作类型哪些索引可以使用哪些索引被实际使用每张表有多少行被优化器查询看到这个表,也许你会两眼一抹黑,这咋看呀?接着往下看,你一定可以从执行计划中轻松得出以上结果。
二、名词段解释
在这里插入图片描述

  1. id 定义:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。
  2. 存在以下三种情况:
  3. id相同,执行顺序由上至下
mysql> desc select e.*,p.* from employee e,performance p where p.user_id = e.id;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                      |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
|  1 | SIMPLE      | e     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL                                       |
|  1 | SIMPLE      | p     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |    50.00 | Using where; Using join buffer (hash join) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

id不同,如果是子查询,id序号对递增,id值越大优先级越高,越先执行

mysql> explain select e.* 
    -> from employee e
    -> where id = ( select user_id
    -> from performance
    -> where performance.score > 80 and performance.year = 2020 and performance.quarter = 2);
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table       | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | e           | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
|  2 | SUBQUERY    | performance | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |    50.00 | Using where |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)

id相同而不同(不同的:id越大越先执行;相同的:由上至下按顺序执行)

mysql> EXPLAIN SELECT
    -> e.*, d.depart_name
    -> FROM employee e,department d
    -> WHERE
    -> e.depart_id = d.id
    -> AND e.id = (
    -> SELECT user_id
    -> WHERE
    -> performance.score > 80
    -> AND performance. YEAR = 2020
    -> AND performance. QUARTER = 2
    -> );
+----+-------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+
| id | select_type | table       | partitions | type   | possible_keys | key     | key_len | ref            | rows | filtered | Extra       |
+----+-------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+
|  1 | PRIMARY     | e           | NULL       | ALL    | NULL          | NULL    | NULL    | NULL           |    1 |   100.00 | Using where |
|  1 | PRIMARY     | d           | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db.e.depart_id |    1 |   100.00 | NULL        |
|  2 | SUBQUERY    | performance | NULL       | ALL    | NULL          | NULL    | NULL    | NULL           |    2 |    50.00 | Using where |
+----+-------------+-------------+------------+--------+---------------+---------+---------+----------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

2、select_type 定义:查询的类型,主要用于区别普通查询、联合查询和子查询等复合查询。
SIMPLE:简单的select查询,查询中不包含子查询和联合查询(union)

mysql> explain select * from employee;
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | employee | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

PRIMARY:若查询中包含任何的子查询,最外层查询则标记为PRIMARYSUBQUERY:在select或where列表中包含的子查询mysql>

explain select e.* 
    -> from employee e
    -> where id = ( select user_id
    -> from performance
    -> where performance.score > 80 and performance.year = 2020 and performance.quarter = 2);
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table       | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | e           | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
|  2 | SUBQUERY    | performance | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |    50.00 | Using where |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)

DERIVED:在FROM列表中包含的子查询被标记为(DERIVED),Mysql会递归执行这些子查询,把结果放在临时表里。

mysql> EXPLAIN select employee.* FROM (SELECT distinct department.id FROM department) s1,employee WHERE s1.id = employee.depart_id;
+----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------------+------+----------+-------------+
| id | select_type | table      | partitions | type  | possible_keys | key         | key_len | ref                   | rows | filtered | Extra       |
+----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------------+------+----------+-------------+
|  1 | PRIMARY     | employee   | NULL       | ALL   | NULL          | NULL        | NULL    | NULL                  |    1 |   100.00 | Using where |
|  1 | PRIMARY     | <derived2> | NULL       | ref   | <auto_key0>   | <auto_key0> | 4       | db.employee.depart_id |    2 |   100.00 | Using index |
|  2 | DERIVED     | department | NULL       | index | PRIMARY       | PRIMARY     | 4       | NULL                  |    4 |   100.00 | Using index |
+----+-------------+------------+------------+-------+---------------+-------------+---------+-----------------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

UNION:如果第二个SELECT出现在UNION之后,则标记为UNION;如果UNION包含在FROM子句的子查询中,外层SELECT被标记为DERIVEDUNION RESULT:从UNION表获取结果的SELECTmysql> explain

select * from employee union select * from employee_asu;
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table        | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY      | employee     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
|  2 | UNION        | employee_asu | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
| NULL | UNION RESULT | <union1,2>   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
3 rows in set, 1 warning (0.00 sec)
mysql> explain select * from (select * from employee union select * from employee_asu) s;
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table        | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY      | <derived2>   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 | NULL            |
|  2 | DERIVED      | employee     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
|  3 | UNION        | employee_asu | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
| NULL | UNION RESULT | <union2,3>   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
+----+--------------+--------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
4 rows in set, 1 warning (0.00 sec)

3、table 定义:顾名思义,表名。4、partitions(分区) 定义:显示表分区的分区名

mysql> explain select * from tk;
+----+-------------+-------+------------+------+---------------+------+---------+---
| id | select_type | table | partitions | type | possible_keys | key  | key_len | re
+----+-------------+-------+------------+------+---------------+------+---------+---
|  1 | SIMPLE      | tk    | p0,p1,p2   | ALL  | NULL          | NULL | NULL    | NU
+----+-------------+-------+------------+------+---------------+------+---------+---
1 row in set, 1 warning (0.00 sec)

5、type 定义:type显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏依次为
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > all,
常见的有system > const > eq_ref > ref > range > index > allsystem:表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,可忽略不计。

mysql> EXPLAIN select * FROM (SELECT distinct department.id FROM department where id=2) s1;
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | PRIMARY     | <derived2> | NULL       | system | NULL          | NULL    | NULL    | NULL  |    1 |   100.00 | NULL        |
|  2 | DERIVED     | department | NULL       | const  | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

const:表示通过索引一次就找到了,const用于比较primary key或者unique索引,只匹配一行数据,速度很快。

mysql> explain SELECT distinct department.id FROM department where id=2;
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table      | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | department | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条数据与之匹配,常见于主键或唯一索引扫描。

mysql> explain SELECT * from employee,department where employee.depart_id  = department.id ;
+----+-------------+------------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref                   | rows | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+
|  1 | SIMPLE      | employee   | NULL       | ALL    | NULL          | NULL    | NULL    | NULL                  |    7 |   100.00 | Using where |
|  1 | SIMPLE      | department | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db.employee.depart_id |    1 |   100.00 | NULL        |
+----+-------------+------------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+

2 rows in set, 1 warning (0.00 sec)
ref:非唯一性索引扫描,返回匹配某个单独值的所有行

mysql> show index from employee; #查看表索引
+----------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table    | Non_unique | Key_name              | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+----------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| employee |          0 | PRIMARY               |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| employee |          1 | idx_employee_username |            1 | username    | A         |           0 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+----------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.00 sec)
mysql> explain select * from employee where username = "john";
+----+-------------+----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys         | key                   | key_len | ref   | rows | filtered | Extra |
+----+-------------+----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_employee_username | idx_employee_username | 83      | const |    1 |   100.00 | NULL  |
+----+-------------+----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.01 sec)

range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引,一般是where语句中出现了between、<、>或in等查询。

mysql> explain select * from employee where id between 1 and 3;
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    3 |   100.00 | Using where |
+----+-------------+----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

index:full index scan,全索引树扫描,通常比all快,因为索引文件比数据文件小很多。

mysql> explain select id from department;
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table      | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | department | NULL       | index | NULL          | PRIMARY | 4       | NULL |    4 |   100.00 | Using index |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

all:全表扫描,当数据量达到百万级别,性能会下降明显,需要建立索引;当然小数据量的全表扫描是没有问题的。

mysql> explain select * from department;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | department | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

6、possible_keys 定义:显示可能应用在这张表中的索引,一个或多个(查询涉及到的字段若存在索引,则该索引将被列出,但不一定被查询实际使用)

mysql> explain select id,username,age,salary from employee where username='a';
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys                        | key                     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_username_age_salary,idx_username | idx_username_age_salary | 83      | const |    1 |   100.00 | Using index |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

补充说明:从执行计划关键字possible_keys中可以看出,sql语句执行可能用到idx_username和idx_username_age_salary两个索引。如果为null,就是没有可能使用的索引。7、key 定义:实际使用的索引。如果为null,则没有使用索引。常规举例

mysql> explain select username,age,salary from employee where username = 'a' group by age,salary;
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys                        | key                     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_username_age_salary,idx_username | idx_username_age_salary | 83      | const |    1 |   100.00 | Using index |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

补充说明:possible_keys,可能使用的所以为idx_username,idx_username_age_salary; key,实际使用的索引为idx_username_age_salary覆盖索引看到覆盖索引也许你两眼一抹黑,别急,先记住这么一个名词,继续往下看。

mysql> explain select username,age,salary from employee;
+----+-------------+----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key                     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | index | NULL          | idx_username_age_salary | 93      | NULL |    7 |   100.00 | Using index |
+----+-------------+----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

补充说明:如果查询中使用了覆盖索引,则该索引只会出现在key中,不会出现在possible_keys中。8、key_len 定义:表示索引中使用的字节数,可通过该列计算查询中使用的索引长度,在不损失精度的情况下,key_len越短越好。换句话说,key_len显示的值为索引字段的最大可能长度,即key_len是通过表定义计算而得,不是通过表内检索出来的,不过具体怎么算出来的没有研究。9、ref 定义:显示索引哪一列别使用了,如果可能的话,是一个常数。指明哪些列或常量被用于查找索引列上的值。

mysql> EXPLAIN SELECT employee.username, employee.age, employee.salary FROM employee, department WHERE employee.id = department.id;
+----+-------------+------------+------------+--------+---------------+---------+---------+------------------+------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref              | rows | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+------------------+------+----------+-------------+
|  1 | SIMPLE      | department | NULL       | index  | PRIMARY       | PRIMARY | 4       | NULL             |    4 |   100.00 | Using index |
|  1 | SIMPLE      | employee   | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db.department.id |    1 |   100.00 | NULL        |
+----+-------------+------------+------------+--------+---------------+---------+---------+------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

补充说明:ref对呀的值为db.department.id,表示数据库db中的department表中的id列。

mysql> EXPLAIN SELECT username,age,salary FROM employee where username = 'john';
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys                        | key                     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_username_age_salary,idx_username | idx_username_age_salary | 83      | const |    1 |   100.00 | Using index |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

补充说明:username对应的值为john,所以是常量const10、rows 定义:根据表的统计信息及索引使用情况,大致估算出找到所需的记录需要读取的行数。11、filtered 定义:这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。值越大越好。12、Extra 定义:包含不适合在其它列中显示但十分重要的的额外信息Using filesort:说明Mysql使用一个外部索引排序,而不是按照表内的索引进行排序(Mysql中无法使用索引完成的排序操作称为“文件排序”)。

mysql> EXPLAIN SELECT username,age,salary FROM employee where username = 'john' order by id;
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-----------------------------+
| id | select_type | table    | partitions | type | possible_keys                        | key                     | key_len | ref   | rows | filtered | Extra                       |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-----------------------------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_username_age_salary,idx_username | idx_username_age_salary | 83      | const |    1 |   100.00 | Using index; Using filesort |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

补充说明:虽然使用了idx_username_age_salary索引,但是排序规则不是按照这个索引来的,而是索引文件外排序。因此sql语句的排序规则尽量按照索引的字段来排序,避免文件外排序,降低性能。using temporary:表示使用了临时表保存了中间结果,Mysql在对查询结果排序时使用临时表,常见于排序order by和分组gruop by。

mysql> explain select age from employee where username in ('john','asd') group by age;
+----+-------------+----------+------------+-------+------------------------------------------------------------+-------------------------+---------+------+------+----------+-------------------------------------------+
| id | select_type | table    | partitions | type  | possible_keys                                              | key                     | key_len | ref  | rows | filtered | Extra                                     |
+----+-------------+----------+------------+-------+------------------------------------------------------------+-------------------------+---------+------+------+----------+-------------------------------------------+
|  1 | SIMPLE      | employee | NULL       | range | idx_username_age_salary,idx_username,idx_username_departid | idx_username_age_salary | 83      | NULL |    2 |   100.00 | Using where; Using index; Using temporary |
+----+-------------+----------+------------+-------+------------------------------------------------------------+-------------------------+---------+------+------+----------+-------------------------------------------+
1 row in set, 1 warning (0.00 sec)

补充说明:产生临时表很消耗性能using index:表示相应的select操作中使用了覆盖索引,避免访问了数据行,效率不错。如果同时出现了using where,表示在索引中查找;如果没有,表明是从索引中读取数据,而非查找。 覆盖索引/索引覆盖(Covering index):select数据列只需要从索引中就可以全部获取,不必读取数据行,换句话说查询列要被所建的索引覆盖。

mysql> explain select username,age,salary from employee where username ='john' order by age,salary;
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys                        | key                     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employee | NULL       | ref  | idx_username_age_salary,idx_username | idx_username_age_salary | 83      | const |    1 |   100.00 | Using index |
+----+-------------+----------+------------+------+--------------------------------------+-------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

注意:要想使用覆盖索引,一定要从select列表中获取自己想要的列,不可使用select ;如果使用所有列做索引会导致索引过于庞大。
using where:sql语句中使用了where过滤
using join buffer:使用了连接缓存
impossible where:where子句中总是false,不可能查到任何数据
select table optimized away:在没有group by的情况下,基于索引优化MIN/MAX操作或者对于MyISAM存储优化count(
)操作,不必等到执行阶段在进行计算,执行计划完成的阶段就完成优化。
distinct:优化distinct操作,再找到第一匹配的元组后就停止找同样值的操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL中,优化查询的一个重要手段就是使用索引。EXPLAIN是用来分析查询语句的工具,可以通过分析EXPLAIN输出结果来进行索引优化。下面是一些常用的优化技巧: 1. 索引覆盖:通过使用覆盖索引,可以避免MySQL访问表格数据,从而提高查询速度。如下所示: ``` EXPLAIN SELECT id FROM table WHERE col1 = 'value'; ``` 在这个查询中,只需要访问索引就可以返回结果,不用访问表格数据。 2. 索引选择:使用合适的索引可以提高查询的效率。一般来说,选择最左前缀列的索引可以让MySQL选择更加有效的索引。如下所示: ``` EXPLAIN SELECT * FROM table WHERE col1 = 'value' AND col2 = 'value2'; ``` 在这个查询中,如果存在(col1, col2)的复合索引,则MySQL会选择它来执行查询,这样可以避免全表扫描。 3. 避免使用函数:在查询中,使用函数会导致MySQL无法使用索引,从而降低查询效率。如下所示: ``` EXPLAIN SELECT * FROM table WHERE YEAR(date_col) = '2021'; ``` 在这个查询中,使用YEAR函数会导致MySQL无法使用(date_col)的索引来执行查询,可以考虑将查询条件改为: ``` EXPLAIN SELECT * FROM table WHERE date_col >= '2021-01-01' AND date_col < '2022-01-01'; ``` 4. 避免使用OR:在查询中,使用OR会导致MySQL无法使用索引,从而降低查询效率。如下所示: ``` EXPLAIN SELECT * FROM table WHERE col1 = 'value1' OR col2 = 'value2'; ``` 在这个查询中,可以考虑将查询条件改为: ``` EXPLAIN SELECT * FROM table WHERE col1 = 'value1' UNION SELECT * FROM table WHERE col2 = 'value2'; ``` 5. 避免全表扫描:全表扫描是一种效率比较低下的查询方式,可以通过优化查询条件或者添加合适的索引来避免全表扫描。如下所示: ``` EXPLAIN SELECT * FROM table WHERE col LIKE '%value%'; ``` 在这个查询中,可以考虑将查询条件改为: ``` EXPLAIN SELECT * FROM table WHERE col LIKE 'value%'; ``` 这样可以使用(col)的索引来执行查询,避免全表扫描。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值