MySQL索引实战 & 执行计划

一、执行计划(只是自己理解)

1,id):
id 相同,执行顺序由上到下,按照我的理解,通常发生于子查询;
id 不同,如果是子查询,id的序号会递增,id越大则优先级越高,越先会被执行;
id 既不同又相同,id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行;

2,select_type):
simple:简单的select查询,查询中不包含子查询或者union;
primary:查询中包含任何复杂的子部分,最外层查询则被标记为primary;
subquery:在select 或 where列表中(除了from字句中包含的子查询外)包含了子查询,可能是subquery;
derived:表示用了临时表;
union result:从union表获取结果的select;

3,table):
显示的查询表名,如果查询使用了别名,那么这里显示的是别名;
如果不涉及对数据表的操作,那么这显示为null;
如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生;
如果是尖括号括起来的<union M,N>,与<derived N>类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集;

4,type)访问数据的方式:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
system:可以忽略不计;
const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const;
eq_ref:看不懂;
ref:普通的索引扫描方式;
all:这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
possible_keys:查询可能使用到的索引都会在这里列出来;如果为NULL,说明没有WHERE条件时查询优化器无法通过索引检索数据。
key:查询真正使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
rows:这里是执行计划中估算的扫描行数,不是精确值。
extra:这个列可以显示的信息非常多,有几十种,常用的有:
    using filesort:排序时无法使用到索引时,就会出现这个。常见于order by和group by语句中。
    using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据(表明使用了覆盖索引)。
    Using index condition, Using where; 用了索引,但是需要回表查找;(目前我的理解是这样)

二、实战

基本哦:

SHOW INDEX FROM test_emp;
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_emp |          0 | PRIMARY      |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| test_emp |          1 | idx_age_name |            1 | age         | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| test_emp |          1 | idx_age_name |            2 | name        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
+----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
rows in set (0.00 sec)

// 使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const;
mysql> EXPLAIN SELECT * FROM test_emp WHERE id = '2';
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | test_emp | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
row in set (0.01 sec)

// type 为 ref,说明用了普通的索引扫描方式
// Using index condition, Using where; 用了索引,但是需要回表查找;(目前我的理解是这样)
mysql> EXPLAIN SELECT * FROM test_emp WHERE age = '22' AND `name` = '111';
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref         | rows | Extra                 |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
|  1 | SIMPLE      | test_emp | ref  | idx_age_name  | idx_age_name | 773     | const,const |    1 | Using index condition |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
row in set (0.00 sec)

// 说明如果都是等号的话,顺序是没有问题的
mysql> EXPLAIN SELECT * FROM test_emp WHERE `name` = '111' AND age = '22';
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref         | rows | Extra                 |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
|  1 | SIMPLE      | test_emp | ref  | idx_age_name  | idx_age_name | 773     | const,const |    1 | Using index condition |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-----------------------+
row in set (0.00 sec)

// 好像这个也没有问题
mysql> EXPLAIN SELECT * FROM test_emp WHERE age = '22';
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref   | rows | Extra |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------+
|  1 | SIMPLE      | test_emp | ref  | idx_age_name  | idx_age_name | 5       | const |    1 | NULL  |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------+
row in set (0.00 sec)

// 这个就没有办法了,因为age在前面
mysql> EXPLAIN SELECT * FROM test_emp WHERE `name` = '111';
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | test_emp | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
row in set (0.00 sec)

// age和name反了
mysql> EXPLAIN SELECT * FROM test_emp WHERE `name` = '111' ORDER BY age;
+----+-------------+----------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra                       |
+----+-------------+----------+------+---------------+------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_emp | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where; Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------+-----------------------------+
row in set (0.00 sec)

// 顺序顺序,age在前,name在后
mysql> EXPLAIN SELECT * FROM test_emp WHERE `age` = '111' ORDER BY `name`;
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref   | rows | Extra       |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | test_emp | ref  | idx_age_name  | idx_age_name | 5       | const |    1 | Using where |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-------------+
row in set (0.00 sec)

// 顺序顺序,age在前,name在后
mysql> EXPLAIN SELECT * FROM test_emp GROUP BY age ORDER BY `name`;
+----+-------------+----------+-------+---------------+--------------+---------+------+------+---------------------------------+
| id | select_type | table    | type  | possible_keys | key          | key_len | ref  | rows | Extra                           |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+---------------------------------+
|  1 | SIMPLE      | test_emp | index | idx_age_name  | idx_age_name | 773     | NULL |    3 | Using temporary; Using filesort |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+---------------------------------+
row in set (0.00 sec)
View Code

 id当然为主键,其外就建立了一个联合索引(注意,联合索引的顺序很重要,很重要)

mysql> SHOW INDEX FROM test_person;
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table       | Non_unique | Key_name      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_person |          0 | PRIMARY       |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| test_person |          1 | idx_age_birth |            1 | age         | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| test_person |          1 | idx_age_birth |            2 | birthday    | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)
View Code

 例子一,注意order by 后面的以及extra下面的,在这里where后面的条件不变:

mysql> explain select * from test_person where age > 20 order by age;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test_person | index | idx_age_birth | idx_age_birth | 11      | NULL |    3 | Using where; Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
1 row in set (0.01 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age > 20 ORDER BY age,birthday;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test_person | index | idx_age_birth | idx_age_birth | 11      | NULL |    3 | Using where; Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age > 20 ORDER BY birthday;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
|  1 | SIMPLE      | test_person | index | idx_age_birth | idx_age_birth | 11      | NULL |    3 | Using where; Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
1 row in set (0.01 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age > 20 ORDER BY birthday,age;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
|  1 | SIMPLE      | test_person | index | idx_age_birth | idx_age_birth | 11      | NULL |    3 | Using where; Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
1 row in set (0.00 sec)
View Code

 例子二,注意order by 后面的以及extra下面的,在这里where后面的条件不变:

mysql> EXPLAIN SELECT * FROM test_person WHERE birthday > '2012-12-12 00:00:00' ORDER BY age;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using where; Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE birthday > '2012-12-12 00:00:00' ORDER BY age,birthday;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using where; Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE birthday > '2012-12-12 00:00:00' ORDER BY birthday;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using where; Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE birthday > '2012-12-12 00:00:00' ORDER BY birthday,age;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                                    |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using where; Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+------------------------------------------+
1 row in set (0.00 sec)
View Code

例子三,这里得出的结论是,要不就得是同时升序,要不就得是同时降序啊,否则用不到索引:

mysql> EXPLAIN SELECT * FROM test_person ORDER BY age DESC;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY birthday DESC;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY age ASC, birthday DESC;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY age DESC, birthday DESC;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-------------+
1 row in set (0.00 sec)
View Code

例子四:

mysql> EXPLAIN SELECT * FROM test_person ORDER BY id;
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+
| id | select_type | table       | type  | possible_keys | key     | key_len | ref  | rows | Extra |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+
|  1 | SIMPLE      | test_person | index | NULL          | PRIMARY | 4       | NULL |    3 | NULL  |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY id,birthday;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY id,age;
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
| id | select_type | table       | type  | possible_keys | key           | key_len | ref  | rows | Extra                       |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_person | index | NULL          | idx_age_birth | 11      | NULL |    3 | Using index; Using filesort |
+----+-------------+-------------+-------+---------------+---------------+---------+------+------+-----------------------------+
1 row in set (0.01 sec)
View Code

三、结论:

1order by子句,尽量使用Index方式排序,在索引列上遵循索引的最佳左前缀原则。 复合(联合)索引形如 key (‘A1’,’A2’,’A3’ ),排序的思路一般是:
  先按照A1来排序,A1相同,然后按照A2排序,以此类推,这样对于(A1),(A1,A2), (A1,A2,A3)的索引都是有效的,但是对于(A2,A3)这样的索引就无效了。尽量避免因索引字段的缺失 或 索引字段顺序的不同 引起的FileSort排序。
2)mysql一次查询只能使用一个索引。如果要对多个字段使用索引,建立复合索引。 ORDER BY 能使用索引最左前缀:
       - ORDER BY a
     - ORDER BY a,b
       - ORDER BY a,b,c
       - ORDER BY a DESC,b DESC,c DESC
   如果 WHERE 使用索引的最左前缀为常量,则 ORDER BY能使用索引:
    - WHERE a = const ORDER BY b,c
    - WHERE a = const AND b = const ORDER BY c
    - WHERE a = const AND b > const ORDER BY b,c
 (请看下面的例子) 不能使用索引进行排序:
    - order by a asc, b desc, c desc (排序不一致嘛)
    - where g = const order by b,c (丢失a索引)
    - where a = const order by c (丢失b索引)
    - where a = const order by a,d (d不是索引的一部分)
    - where a in(...) order by b,c (对于排序来说,多个相等的条件也是范围查询)
    - 如果a,b分别建立了一个索引(不是普通索引,而是联合索引),对于这样的排序 order by a,b 是不会走索引
    - 如果查询条件为函数,也无法使用索引

例子一:

mysql> SHOW INDEX FROM test_person;
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table       | Non_unique | Key_name      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_person |          0 | PRIMARY       |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| test_person |          1 | idx_age_birth |            1 | age         | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| test_person |          1 | idx_age_birth |            2 | name        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| test_person |          1 | idx_age_birth |            3 | birthday    | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
rows in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age = 1 AND name > 22 ORDER BY name,birthday;
+----+-------------+-------------+------+---------------+---------------+---------+-------+------+--------------------------+
| id | select_type | table       | type | possible_keys | key           | key_len | ref   | rows | Extra                    |
+----+-------------+-------------+------+---------------+---------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | test_person | ref  | idx_age_birth | idx_age_birth | 5       | const |    1 | Using where; Using index |
+----+-------------+-------------+------+---------------+---------------+---------+-------+------+--------------------------+
row in set (0.01 sec)
View Code

 例子二:

mysql> SHOW INDEX FROM test_person;
+-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table       | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_person |          0 | PRIMARY  |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| test_person |          1 | idx_age  |            1 | age         | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
| test_person |          1 | idx_name |            1 | name        | A         |           3 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
rows in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person ORDER BY age,name;
+----+-------------+-------------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | test_person | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using filesort |
+----+-------------+-------------+------+---------------+------+---------+------+------+----------------+
row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age = 22 ORDER BY age;
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table       | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | test_person | ref  | idx_age       | idx_age | 5       | const |    1 | NULL  |
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-------+
row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM test_person WHERE age = 22 ORDER BY name;
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-----------------------------+
| id | select_type | table       | type | possible_keys | key     | key_len | ref   | rows | Extra                       |
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | test_person | ref  | idx_age       | idx_age | 5       | const |    1 | Using where; Using filesort |
+----+-------------+-------------+------+---------------+---------+---------+-------+------+-----------------------------+
row in set (0.01 sec)
mysql> EXPLAIN SELECT * FROM test_person WHERE birthday = NOW() ORDER BY name;
+----+-------------+-------------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows | Extra                       |
+----+-------------+-------------+------+---------------+------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | test_person | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where; Using filesort |
+----+-------------+-------------+------+---------------+------+---------+------+------+-----------------------------+
row in set (0.01 sec)
View Code

group by与order by的索引优化基本一样,group by实质是先排序后分组,也就是分组之前必排序,遵照索引的最佳左前缀原则可以大大提高group by的效率。

原文地址:https://www.cnblogs.com/ericguoxiaofeng/p/8638912.html