上午领导问我,开发写的一个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)