Mysql复合索引选取规则问题

先创建测试数据表
CREATE TABLE `test`.`composite_index_test`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `phone` bigint(15) NOT NULL,
  `sex` enum('0','1') NULL,
  `age` tinyint(4) NULL,
  `city` varchar(50) NULL,
  `email` varchar(50) NULL,
  `address` varchar(255) NULL,
  PRIMARY KEY (`id`, `name`, `phone`)
)

复合主键为 id, name, phone

创建MySQL函数
#生成随机字符串
DELIMITER $$ 
CREATE FUNCTION rand_strings(n INT) RETURNS VARCHAR(255)
BEGIN
	shochars_str VARCHAR(50) DEFAULT 'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	DECLARE return_str VARCHAR(255) DEFAULT '';
	DECLARE i INT DEFAULT 0;
	WHILE i < n DO
	SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
	SET i = i+1;
	END WHILE;
	RETURN return_str;
END $$
DELIMITER ;


#生成随机数字
DELIMITER $$ 
CREATE FUNCTION rand_num() RETURNS INT(5)
BEGIN
	DECLARE i INT DEFAULT 0;
	SET i = FLOOR(RAND()*99999);
	RETURN i;
END $$
DELIMITER ;

可生成随机字符串和数字

创建存储过程
DELIMITER $$
CREATE PROCEDURE insert_test(IN max_num INT(10))
BEGIN
	DECLARE i INT DEFAULT 0;
	# set autocommit =0 把autocommit设置成0,把默认提交关闭
	SET autocommit = 0;
	REPEAT
	SET i = i + 1;
	INSERT INTO composite_index_test(name,phone,sex,age,city,email,address) VALUES (rand_strings(6),rand_num(),23,rand_strings(2),rand_strings(12),rand_strings(30));
	UNTIL i = max_num
	END REPEAT;
	COMMIT;
END $$
DELIMITER ;
执行存储过程
#添加10w数据
call insert_test(100000);
生成数据库如下:Mysql复合索引选取规则问题_第1张图片
使用索引id ~~~~~命中索引
mysql> explain select * from composite_index_test where id=77777;
+----+-------------+----------------------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table                | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+----------------------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | composite_index_test | ref  | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+----------------------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.05 sec)`
使用索引id、name ~~~~~命中索引
mysql> explain select * from composite_index_test where id=77777 and name='NpowtD';
+----+-------------+----------------------+------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table                | type | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+----------------------+------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | composite_index_test | ref  | PRIMARY       | PRIMARY | 26      | const,const |    1 | Using where |
+----+-------------+----------------------+------+---------------+---------+---------+-------------+------+-------------+
1 row in set (0.04 sec)
使用索引id、name、phone ~~~~~命中索引
mysql> explain select * from composite_index_test where id=77777 and name='NpowtD' and phone=72597;
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref               | rows | Extra |
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
|  1 | SIMPLE      | composite_index_test | const | PRIMARY       | PRIMARY | 34      | const,const,const |    1 |       |
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
使用索引name ~~~~~未命中索引
mysql> explain select * from composite_index_test where name='NpowtD';
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table                | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | composite_index_test | ALL  | NULL          | NULL | NULL    | NULL | 1000754 | Using where |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.05 sec)
使用索引phone ~~~~~未命中索引
mysql> explain select * from composite_index_test where phone=72597;
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table                | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | composite_index_test | ALL  | NULL          | NULL | NULL    | NULL | 1000754 | Using where |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.05 sec)
使用索引name、phone ~~~~~未命中索引
mysql> explain select * from composite_index_test where name='GrRioV' and  phone=72597;
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table                | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | composite_index_test | ALL  | NULL          | NULL | NULL    | NULL | 1000754 | Using where |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
使用索引phone、name、id ~~~~~命中索引
mysql> explain select * from composite_index_test where name='GrRioV' and  phone=72597 and id=37061;
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref               | rows | Extra |
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
|  1 | SIMPLE      | composite_index_test | const | PRIMARY       | PRIMARY | 34      | const,const,const |    1 |       |
+----+-------------+----------------------+-------+---------------+---------+---------+-------------------+------+-------+
使用索引phone、id、name但是用or连接 ~~~~~未命中索引
mysql> explain select * from composite_index_test where name='GrRioV' and  phone=72597 or id=37061;
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table                | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | composite_index_test | ALL  | PRIMARY       | NULL | NULL    | NULL | 1000754 | Using where |
+----+-------------+----------------------+------+---------------+------+---------+------+---------+-------------+


mysql> explain select * from composite_index_test where name='GrRioV' or  phone=72597 and id=37061;
+----+-------------+----------------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table                | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+----------------------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | composite_index_test | ALL  | PRIMARY       | NULL | NULL    | NULL | 998639 | Using where |
+----+-------------+----------------------+------+---------------+------+---------+------+--------+-------------+
使用索引phone、id、name但是非等于条件

*小于的情况 ~~~~~命中索引*

mysql> explain select * from composite_index_test where name='GrRioV' and  phone=72597 and  id<37069;
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref  | rows  | Extra       |
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-------------+
|  1 | SIMPLE      | composite_index_test | range | PRIMARY       | PRIMARY | 4       | NULL | 73776 | Using where |
+----+-------------+----------------------+-------+---------------+---------+---------+------+-------+-------------+

*大于的情况~~~~~命中索引*

mysql> explain select * from composite_index_test where id>37069;
+----+-------------+----------------------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table                | type  | possible_keys | key     | key_len | ref  | rows   | Extra       |
+----+-------------+----------------------+-------+---------------+---------+---------+------+--------+-------------+
|  1 | SIMPLE      | composite_index_test | range | PRIMARY       | PRIMARY | 4       | NULL | 499319 | Using where |
+----+-------------+----------------------+-------+---------------+---------+---------+------+--------+-------------+

结论

  1. 至少使用复合索引的第一个索引并且用and连接查询条件,可触发索引的使用
  2. 没有使用第一个复合索引,不触发索引的使用
  3. 使用大于/小于不影响索引的选择
  4. 使用or不会命中索引

你可能感兴趣的:(MySQL)