复合索引的优化问题

上午领导问我,开发写的一个sql里面用到的复合索引,要是里面字段的顺序乱了是否还会走索引。

于是在我的测试环境做了如下测试来验证:
mysql> show create table t_index;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_index | CREATE TABLE `t_index` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name1` char(20) COLLATE utf8_bin DEFAULT NULL,
  `name2` char(20) COLLATE utf8_bin DEFAULT NULL,
  `name3` char(20) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `com_ind` (`name1`,`name2`,`name3`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COLLATE=utf8_bin |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

插入26行数据格式大概是大写,小写,双小写。
mysql> select * from t_indexl
-> ;
ERROR 1146 (42S02): Table 'xuning.t_indexl' doesn't exist
mysql> select * from t_index;
+----+-------+-------+-------+
| id | name1 | name2 | name3 |
+----+-------+-------+-------+
| 1 | A | a | aa |
| 3 | B | b | bb |
| 4 | C | c | cc |
| 5 | D | d | dd |
| 6 | E | e | ee |
| 7 | F | f | ff |
| 8 | G | g | gg |
| 9 | H | h | hh |
| 10 | I | i | ii |
| 11 | J | j | jj |
| 12 | K | k | kk |
| 13 | L | l | ll |
| 14 | M | m | mm |
| 15 | N | n | nn |
| 16 | O | o | oo |
| 17 | P | p | pp |
| 18 | Q | q | qq |
| 19 | R | r | rr |
| 20 | S | s | ss |
| 21 | T | t | tt |
| 22 | U | u | uu |
| 23 | V | v | vv |
| 24 | W | w | ww |
| 25 | X | x | xx |
| 26 | Y | y | yy |
| 27 | Z | z | zz |
+----+-------+-------+-------+
26 rows in set (0.00 sec)

分别做了如下查询:
explain select * from t_index where name2='m' and name3='mm' and name1='M';
explain select * from t_index where name1='M' and name2='m' and name3='mm';
explain select * from t_index where name2='m' and name3='mm'; ##没有用到索引 最左匹配原则
explain select * from t_index where name1='M' and name3='mm';
explain select * from t_index where name1='M' and name2='m';
explain select * from t_index where name2='m' and name1='M' ;
explain select * from t_index where name2='m' and name1='M' ;
explain select * from t_index where name1='M';
explain select * from t_index where name2='m';
explain select * from t_index where name3='mm';


mysql> explain select * from t_index where name2='m' and name3='mm' and name1='M';
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref               | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 183     | const,const,const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
1 row in set, 1 warning (0.02 sec)

mysql> explain select * from t_index where name1='M' and name2='m' and name3='mm';
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref               | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 183     | const,const,const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where  name2='m' and name3='mm';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | t_index | NULL       | index | NULL          | com_ind | 183     | NULL |   26 |     3.85 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where name1='M' and name3='mm';
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+--------------------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 61      | const |    1 |    10.00 | Using where; Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+--------------------------+
1 row in set, 1 warning (0.01 sec)

mysql> explain select * from t_index where name1='M';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    39
Current database: xuning

+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 61      | const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.06 sec)

mysql> explain select * from t_index where name2='m';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | t_index | NULL       | index | NULL          | com_ind | 183     | NULL |   26 |    10.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where name3='mm';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | t_index | NULL       | index | NULL          | com_ind | 183     | NULL |   26 |    10.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where name1='M' and name2='m';
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 122     | const,const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where name2='m' and name1='M' ;
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 122     | const,const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t_index where name2='m' and name1='M' ;
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | t_index | NULL       | ref  | com_ind       | com_ind | 122     | const,const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)


大致结果如下:
查询在单个字段的,name1,name2,name3分别都用到了索引。

两个字段的,(name1,name2),(name1,name3)(name2,name3)两个字段无论正反写都用到索引。
(name2,name3)没有用到索引

三个字段的,(name1,name2,name3)也会用到索引。

查了相关资料,表示复合索引中匹配最左前缀,所以多个字段里面只有没有用到name1的不会用到索引。(name2,name3)

猜你喜欢

转载自blog.csdn.net/Xun_Jia/article/details/80065504