CREATE TABLE student (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(128) DEFAULT NULL,
age int(11) NOT NULL,
update_time timestamp NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_name_age (name,age),
KEY idx_name_age_update_time (name,age,update_time)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
我使用EXPLAIN
来获取索引在MySQL中如何工作的一些信息,当我像这样执行sql时,我发现一件事让我感到困惑:
EXPLAIN
SELECT * FROM springboot.student
WHERE id>1 AND id <5 AND NAME = 'tank' AND age =23 ;
结果:
id select_type table type possible_keys key key_len ref rows Extra
------ ----------- ------- ------ --------------------------------------------- ------------ ------- ----------- ------ -------------
1 SIMPLE student ref PRIMARY,idx_name_age,idx_name_age_update_time idx_name_age 391 const,const 1 Using where
我想知道为什么我会遇到这个。
最佳答案
没有固有的优先级。您影响 SQL 优化器,但无法控制它。这实际上很好。基于规则的优化器已经过时相当长一段时间了,而基于成本的优化器则风靡一时。
所发生的情况是,[基于成本的] SQL 优化器会生成一个依赖于许多参数的执行计划。例如:
- 表格的大小。
- 存在索引。
- 每列值的分布。
- 过滤条件的选择性。
- 表格统计信息的最新情况。
- 等等
您似乎希望使用主键通过索引读取表。转换为优化器术语,您想要:
- 访问:通过主键索引,使用索引范围扫描。
- 过滤:按
NAME = 'tank' AND 年龄 = 23
。
但是优化器决定做一些不同的事情:
- 访问:通过索引
(姓名、年龄)
,使用索引查找。 - 过滤:按主键索引。
一般来说,索引查找比索引范围扫描快得多。也许这就是优化器选择第二个的原因。
你真的测量过执行时间吗?请记住,计划不是查询。测量,测量,测量。
关于mysql - MySQL中主键和多列索引的优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51053571/