Mysql系列-性能优化神器EXPLAIN使用介绍及分析

 MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化。

 EXPLAIN 命令用法十分简单, 在 SELECT 语句前加上 Explain 就可以了, 例如:

EXPLAIN SELECT * from user_info WHERE id < 300;

下面是我结合我自己创建的表以及执行相关sql语句总结的相关知识点。

准备

为了接下来方便演示 EXPLAIN 的使用, 首先我们需要建立两个测试用的表, 并添加相应的数据:

DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers`  (
  `customerNumber` int(11) NOT NULL,
  `customerName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `contactLastName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `contactFirstName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `phone` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `addressLine1` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `addressLine2` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `city` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `state` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `postalCode` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `country` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `salesRepEmployeeNumber` int(11) NULL DEFAULT NULL,
  `creditLimit` decimal(10, 2) NULL DEFAULT NULL,
  PRIMARY KEY (`customerNumber`) USING BTREE,
  INDEX `salesRepEmployeeNumber`(`salesRepEmployeeNumber`) USING BTREE,
  INDEX `customers_idx_combine_1`(`customerName`, `phone`, `customerNumber`) USING BTREE,
  CONSTRAINT `customers_ibfk_1` FOREIGN KEY (`salesRepEmployeeNumber`) REFERENCES `employees` (`employeeNumber`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `employees`;
CREATE TABLE `employees`  (
  `employeeNumber` int(11) NOT NULL,
  `lastName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `firstName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `extension` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `officeCode` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `reportsTo` int(11) NULL DEFAULT NULL,
  `jobTitle` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`employeeNumber`) USING BTREE,
  INDEX `reportsTo`(`reportsTo`) USING BTREE,
  INDEX `officeCode`(`officeCode`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

创建表成功后,插入一些测试数据。

EXPLAIN 输出格式

EXPLAIN 命令的输出内容大致如下:

mysql> EXPLAIN SELECT * FROM customers WHERE customerName='Herkku Gifts' AND phone='+47 2267 3215' AND customerNumber=167;
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys                   | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY,customers_idx_combine_1 | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

各列的含义如下:

  • id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符
  • select_type: SELECT 查询的类型
  • table: 查询的是哪个表
  • partitions: 匹配的分区
  • type: join 类型
  • possible_keys: 此次查询中可能选用的索引
  • key: 此次查询中确切使用到的索引
  • ken_len: 表示查询优化器使用了索引的字节数
  • ref: 哪个字段或常数与 key 一起被使用
  • rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
  • filtered: 表示此查询条件所过滤的数据的百分比
  • extra: 额外的信息

接下来我们详细看一下每个字段的具体含义:

select_type

select_type 表示了查询的类型, 它的常用取值有:

  • SIMPLE:表示此查询不包含 UNION 查询或子查询

  • PRIMARY:表示此查询是最外层的查询

  • UNION:表示此查询是 UNION 的第二或随后的查询

  • DEPENDENT UNION:UNION 中的第二个或后面的查询语句, 取决于外面的查询

  • UNION RESULT:UNION 的结果

  • SUBQUERY:子查询中的第一个 SELECT

  • DEPENDENT SUBQUERY:子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果

  • DERIVED:当子查询是from子句时,其select_type为DERIVED

最常见的查询类别应该是 SIMPLE 了, 比如当我们的查询没有子查询, 也没有 UNION 查询时, 那么通常就是 SIMPLE 类型, 例如:

1.SIMPLE 情况:

mysql> EXPLAIN SELECT * FROM customers WHERE customerName='Herkku Gifts' AND phone='+47 2267 3215' AND customerNumber=167;
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys                   | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY,customers_idx_combine_1 | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------------------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

2.UNION情况

  当通过union来连接多个查询结果时,第二个之后的select其select_type为UNION

mysql> EXPLAIN SELECT customerNumber FROM customers WHERE customerNumber IN (125,144) UNION SELECT customerNumber FROM customers WHERE country IN ('USA','France');
+----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type  | table      | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | PRIMARY      | customers  | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    2 |   100.00 | Using where; Using index |
|  2 | UNION        | customers  | NULL       | ALL   | NULL          | NULL    | NULL    | NULL |  122 |    20.00 | Using where              |
| NULL | UNION RESULT | <union1,2> | NULL       | ALL   | NULL          | NULL    | NULL    | NULL | NULL |     NULL | Using temporary          |
+----+--------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

3.DEPENDENT UNION与DEPENDENT SUBQUERY

  当union作为子查询时,其中第二个union的select_type就是DEPENDENT UNION。第一个子查询的select_type则是DEPENDENT SUBQUERY

mysql> EXPLAIN SELECT * FROM customers WHERE customerNumber IN (SELECT customerNumber FROM customers WHERE customerNumber IN (125,144) UNION SELECT customerNumber FROM customers WHERE country IN ('USA','France'));
+----+--------------------+------------+------------+--------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type        | table      | partitions | type   | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+--------------------+------------+------------+--------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | PRIMARY            | customers  | NULL       | ALL    | NULL          | NULL    | NULL    | NULL |  122 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | customers  | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | func |    1 |   100.00 | Using where; Using index |
|  3 | DEPENDENT UNION    | customers  | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | func |    1 |    20.00 | Using where              |
| NULL | UNION RESULT       | <union2,3> | NULL       | ALL    | NULL          | NULL    | NULL    | NULL | NULL |     NULL | Using temporary          |
+----+--------------------+------------+------------+--------+---------------+---------+---------+------+------+----------+--------------------------+
4 rows in set, 1 warning (0.00 sec)

4.SUBQUERY

  子查询中的第一个select其select_type为SUBQUERY

mysql> EXPLAIN SELECT * FROM customers WHERE customerNumber=(SELECT customerNumber FROM customers WHERE customerNumber=124);
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | PRIMARY     | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL        |
|  2 | SUBQUERY    | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM customers WHERE customerNumber in (SELECT customerNumber FROM customers WHERE customerNumber=124);
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

思考下为什么一个用了in一个用了=反而select_type就不一样了????

5.DERIVED

mysql> EXPLAIN SELECT * FROM (SELECT COUNT(*) FROM customers WHERE customerNumber=124) a;
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| 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     | customers  | NULL       | const  | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

table

表示查询涉及的表或衍生表

partitions 

匹配的分区

type

type 字段比较重要, 显示连接使用了何种类型。从最好到最差的连接类型依次分别为consteq_regrefrangeindexALL 它提供了判断查询是否高效的重要依据依据。

通过 type 字段, 我们判断此次查询是 全表扫描 还是 索引扫描 等。

 type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
  一般来说,得保证查询至少达到range级别,最好能达到ref。

type 常用的取值有:

  system: 表中只有一条数据. 这个类型是特殊的 const 类型。

  const: 针对主键或唯一索引的等值查询扫描, 最多只返回一行数据。const 查询速度非常快, 因为它仅仅读取一次即可。

  表示通过索引一次就找到了,const用于比较primary key 或者 unique索引。因为只需匹配一行数据,所有很快。如果将主键置于where列表中,mysql就能将该查询转换为一个const 。

  例如下面的这个查询, 它使用了主键索引, 因此 type 就是 const 类型的

mysql> EXPLAIN SELECT * FROM customers WHERE customerNumber=128;
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

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

mysql> SELECT * FROM items;
+----+---------+
| id | item_no |
+----+---------+
|  1 | A-1     |
|  2 | A-2     |
|  3 | A-3     |
|  4 | A-4     |
|  5 | A-5     |
|  6 | A-10    |
|  7 | A-11    |
|  8 | A-20    |
|  9 | A-30    |
+----+---------+
9 rows in set (0.00 sec)
mysql> SELECT * FROM customers LIMIT 10;
+----------------+------------------------------+-----------------+------------------+-------------------+------------------------------+--------------+---------------+----------+------------+-----------+------------------------+-------------+
| customerNumber | customerName                 | contactLastName | contactFirstName | phone             | addressLine1                 | addressLine2 | city          | state    | postalCode | country   | salesRepEmployeeNumber | creditLimit |
+----------------+------------------------------+-----------------+------------------+-------------------+------------------------------+--------------+---------------+----------+------------+-----------+------------------------+-------------+
|            103 | Atelier graphique            | Schmitt         | Carine           | 40.32.2555        | 54, rue Royale               | NULL         | Nantes        | NULL     | 44000      | France    |                   1370 |    21000.00 |
|            112 | Signal Gift Stores           | King            | Jean             | 7025551838        | 8489 Strong St.              | NULL         | Las Vegas     | NV       | 83030      | USA       |                   1166 |    71800.00 |
|            114 | Australian Collectors, Co.   | Ferguson        | Peter            | 03 9520 4555      | 636 St Kilda Road            | Level 3      | Melbourne     | Victoria | 3004       | Australia |                   1611 |   117300.00 |
|            119 | La Rochelle Gifts            | Labrune         | Janine           | 40.67.8555        | 67, rue des Cinquante Otages | NULL         | Nantes        | NULL     | 44000      | France    |                   1370 |   118200.00 |
|            121 | Baane Mini Imports           | Bergulfsen      | Jonas            | 07-98 9555        | Erling Skakkes gate 78       | NULL         | Stavern       | NULL     | 4110       | Norway    |                   1504 |    81700.00 |
|            124 | Mini Gifts Distributors Ltd. | Nelson          | Susan            | 4155551450        | 5677 Strong St.              | NULL         | San Rafael    | CA       | 97562      | USA       |                   1165 |   210500.00 |
|            125 | Havel & Zbyszek Co           | Piestrzeniewicz | Zbyszek          | (26) 642-7555     | ul. Filtrowa 68              | NULL         | Warszawa      | NULL     | 01-012     | Poland    |                   NULL |        0.00 |
|            128 | Blauer See Auto, Co.         | Keitel          | Roland           | +49 69 66 90 2555 | Lyonerstr. 34                | NULL         | Frankfurt     | NULL     | 60528      | Germany   |                   1504 |    59700.00 |
|            129 | Mini Wheels Co.              | Murphy          | Julie            | 6505555787        | 5557 North Pendale Street    | NULL         | San Francisco | CA       | 94217      | USA       |                   1165 |    64600.00 |
|            131 | Land of Toys Inc.            | Lee             | Kwai             | 2125557818        | 897 Long Airport Avenue      | NULL         | NYC           | NY       | 10022      | USA       |                   1323 |   114900.00 |
+----------------+------------------------------+-----------------+------------------+-------------------+------------------------------+--------------+---------------+----------+------------+-----------+------------------------+-------------+
10 rows in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM items,customers WHERE customers.customerNumber=items.id;
+----+-------------+-----------+------------+--------+---------------+---------+---------+-------------------+------+----------+-------+
| id | select_type | table     | partitions | type   | possible_keys | key     | key_len | ref               | rows | filtered | Extra |
+----+-------------+-----------+------------+--------+---------------+---------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | items     | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL              |    9 |   100.00 | NULL  |
|  1 | SIMPLE      | customers | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | yiibaidb.items.id |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+--------+---------------+---------+---------+-------------------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

注意:ALL全表扫描的表是记录最少的表如items表。

ref:非唯一性索引扫描,返回匹配某个单独值的所有行。本质是也是一种索引访问,它返回所有匹配某个单独值的行,然而他可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体 。

mysql> SELECT * FROM customers WHERE salesRepEmployeeNumber=1165;
+----------------+------------------------------+-----------------+------------------+------------+---------------------------+--------------+---------------+-------+------------+---------+------------------------+-------------+
| customerNumber | customerName                 | contactLastName | contactFirstName | phone      | addressLine1              | addressLine2 | city          | state | postalCode | country | salesRepEmployeeNumber | creditLimit |
+----------------+------------------------------+-----------------+------------------+------------+---------------------------+--------------+---------------+-------+------------+---------+------------------------+-------------+
|            124 | Mini Gifts Distributors Ltd. | Nelson          | Susan            | 4155551450 | 5677 Strong St.           | NULL         | San Rafael    | CA    | 97562      | USA     |                   1165 |   210500.00 |
|            129 | Mini Wheels Co.              | Murphy          | Julie            | 6505555787 | 5557 North Pendale Street | NULL         | San Francisco | CA    | 94217      | USA     |                   1165 |    64600.00 |
|            161 | Technics Stores Inc.         | Hashimoto       | Juri             | 6505556809 | 9408 Furth Circle         | NULL         | Burlingame    | CA    | 94217      | USA     |                   1165 |    84600.00 |
|            321 | Corporate Gift Ideas Co.     | Brown           | Julie            | 6505551386 | 7734 Strong St.           | NULL         | San Francisco | CA    | 94217      | USA     |                   1165 |   105000.00 |
|            450 | The Sharp Gifts Warehouse    | Frick           | Sue              | 4085553659 | 3086 Ingle Ln.            | NULL         | San Jose      | CA    | 94217      | USA     |                   1165 |    77600.00 |
|            487 | Signal Collectibles Ltd.     | Taylor          | Sue              | 4155554312 | 2793 Furth Circle         | NULL         | Brisbane      | CA    | 94217      | USA     |                   1165 |    60300.00 |
+----------------+------------------------------+-----------------+------------------+------------+---------------------------+--------------+---------------+-------+------------+---------+------------------------+-------------+
6 rows in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM customers WHERE salesRepEmployeeNumber=1165;
+----+-------------+-----------+------------+------+------------------------+------------------------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys          | key                    | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+------+------------------------+------------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | customers | NULL       | ref  | salesRepEmployeeNumber | salesRepEmployeeNumber | 5       | const |    6 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+------------------------+------------------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
mysql> show index from customers;
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name                | Seq_in_index | Column_name            | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| customers |          0 | PRIMARY                 |            1 | customerNumber         | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | salesRepEmployeeNumber  |            1 | salesRepEmployeeNumber | A         |          16 |     NULL | NULL   | YES  | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            1 | customerName           | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            2 | phone                  | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            3 | customerNumber         | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
5 rows in set (0.00 sec)

range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。一般就是在where语句中出现了bettween、<、>、in等的查询。这种索引列上的范围扫描比全索引扫描要好。只需要开始于某个点,结束于另一个点,不用扫描全部索引 。

mysql> EXPLAIN SELECT * FROM customers WHERE customerNumber BETWEEN 1 AND 120;
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    4 |   100.00 | Using where |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

index:Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常为ALL快,因为索引文件通常比数据文件小。(Index与ALL虽然都是读全表,但index是从索引中读取,而ALL是从硬盘读取) 。

mysql> EXPLAIN SELECT id FROM items;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | items | NULL       | index | NULL          | PRIMARY | 4       | NULL |    9 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> show index from items;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| items |          0 | PRIMARY  |            1 | id          | A         |           9 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

ALL:Full Table Scan,遍历全表以找到匹配的行 。

mysql> EXPLAIN SELECT item_no FROM items;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | items | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    9 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> show index from items;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| items |          0 | PRIMARY  |            1 | id          | A         |           9 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

possible_keys

查询涉及到的字段上存在索引,则该索引将被列出,但不一定被查询实际使用。

key

实际使用的索引,如果为NULL,则没有使用索引。 
查询中如果使用了覆盖索引,则该索引仅出现在key列表中。

mysql> show index from customers;
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name                | Seq_in_index | Column_name            | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| customers |          0 | PRIMARY                 |            1 | customerNumber         | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | salesRepEmployeeNumber  |            1 | salesRepEmployeeNumber | A         |          16 |     NULL | NULL   | YES  | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            1 | customerName           | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            2 | phone                  | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
| customers |          1 | customers_idx_combine_1 |            3 | customerNumber         | A         |         122 |     NULL | NULL   |      | BTREE      |         |               |
+-----------+------------+-------------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
5 rows in set (0.00 sec)

mysql> EXPLAIN SELECT customerName,phone,customerNumber from customers;
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key                     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | index | NULL          | customers_idx_combine_1 | 308     | NULL |  122 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

上述customerName,phone,customerNumber与customers_idx_combine_1索引顺序一致,为覆盖索引

mysql> EXPLAIN SELECT phone,customerName,customerNumber from customers;
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key                     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | index | NULL          | customers_idx_combine_1 | 308     | NULL |  122 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+-------------------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> EXPLAIN SELECT customerName,phone,customerNumber,state from customers;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | customers | NULL       | ALL  | NULL          | NULL | NULL    | NULL |  122 |   100.00 | NULL  |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

state字段为非索引列。

key_len

表示索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len是根据表定义计算而得的,不是通过表内检索出的。

ref

显示索引的那一列被使用了,如果可能,是一个常量const。

mysql> EXPLAIN SELECT customerNumber FROM customers WHERE customerNumber=114;
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

 

rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。

 

Extra

不适合在其他字段中显示,但是十分重要的额外信息。

Using filesort :mysql对数据使用一个外部的索引排序,而不是按照表内的索引进行排序读取。也就是说mysql无法利用索引完成的排序操作成为“文件排序” 。

原文地址:https://www.cnblogs.com/MrFiona/p/10925919.html