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 age = 23
.
然而,优化器决定采取不同的措施:
- 访问:通过索引
(name, age)
,使用索引查找。 - 筛选:按主键索引。
通常,索引搜索比索引范围扫描快得多。也许这就是优化器选择第二个的原因。
你真的测量了执行时间吗?请记住,计划不是查询。测量,测量,测量。