MySQL查询为何选用唯一索引而非联合索引?技术疑问
MySQL索引选择疑问:唯一索引vs联合索引
表结构信息
建表语句如下:
CREATE TABLE `yonghu` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间', `zhanghao` varchar(200) NOT NULL COMMENT '账号', `mima` varchar(200) NOT NULL COMMENT '密码', `xingming` varchar(200) NOT NULL COMMENT '姓名', `xingbie` varchar(200) DEFAULT NULL COMMENT '性别', `lianxidianhua` varchar(200) DEFAULT NULL COMMENT '联系电话', `member` int DEFAULT '0', `discounts` int DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `zhanghao` (`zhanghao`), KEY `idx_zhanghao_member` (`zhanghao`,`member`) ) ENGINE=InnoDB AUTO_INCREMENT=1707209867641 DEFAULT CHARSET=utf8mb3 COMMENT='用户表'
其中zhanghao为唯一索引,同时存在zhanghao+member的联合索引idx_zhanghao_member。
第一次查询及执行计划
执行SQL:
EXPLAIN select member from yonghu where zhanghao ="asd";
执行计划结果:
+----+-------------+--------+------------+-------+------------------------------+----------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+-------+------------------------------+----------+---------+-------+------+----------+-------+ | 1 | SIMPLE | yonghu | NULL | const | zhanghao,idx_zhanghao_member | zhanghao | 602 | const | 1 | 100.00 | NULL | +----+-------------+--------+------------+-------+------------------------------+----------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
疑问点
我原以为联合索引会更快,但MySQL却选择了唯一索引,这是为什么?删除zhanghao唯一索引后,查询会使用联合索引,此时EXPLAIN的type为ref,而使用唯一索引时type为const。从type来看唯一索引效率更高,但联合索引不需要回表,难道不该更快吗?
删除唯一索引后的查询及执行计划
删除zhanghao唯一索引后,执行SQL:
EXPLAIN select addtime from yonghu where zhanghao ="asd";
执行计划结果:
+----+-------------+--------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | yonghu | NULL | ref | idx_zhanghao_member | idx_zhanghao_member | 602 | const | 1 | 100.00 | NULL | +----+-------------+--------+------------+------+---------------------+---------------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
问题解答
- 唯一索引的
const类型具备绝对确定性:因为zhanghao是唯一索引,MySQL能确定通过该索引可以直接定位到唯一一行数据,const是MySQL中效率最高的查询类型之一,优化器会优先选择这种能精准命中单行的索引路径。 - 单行场景下覆盖索引的优势被抵消:虽然联合索引
idx_zhanghao_member是覆盖索引(包含查询字段member)不需要回表,但唯一索引即使需要回表,也仅需读取单行数据,回表的IO开销几乎可以忽略。优化器计算后认为,const类型的访问成本比ref类型更低,覆盖索引的优势不足以逆转这个判断。 - 优化器的成本计算逻辑:MySQL优化器会基于表的统计信息(如数据行数、索引基数等)计算不同索引的查询成本,包括IO和CPU开销。在单行查询场景下,
const类型的直接定位带来的成本下降,远大于覆盖索引节省的回表开销。 - 覆盖索引优势的凸显场景:当查询包含多个字段且都在联合索引中,或者表数据量极大导致回表IO开销显著增加时,覆盖索引的优势才会被优化器优先考虑,此时联合索引可能成为首选。
内容的提问来源于stack exchange,提问作者xuekuo hu
相关产品推荐
相关产品推荐

