You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何InnoDB执行count(customer_id)时选用idx_fk_store_id而非主键索引?

InnoDB执行count(customer_id)时选择二级索引而非主键索引的原因

环境信息

  • 操作系统:CentOS 7
  • MySQL版本:5.7.39
  • 数据库:sakila
  • 目标表:customer

问题详情

执行语句select count(customer_id) from customer时,通过explain查看执行计划,发现InnoDB选择了二级索引idx_fk_store_id而非主键索引:

typekeyExtra
indexidx_fk_store_idUsing index

表的建表语句如下:

CREATE TABLE `customer`(
`customer_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`store_id`   tinyint(3) unsigned NOT NULL,
PRIMARY KEY(`customer_id`),
KEY `idx_fk_store_id`(`store_id`)
) ENGINE=InnoDB AUTO_INCREMENT=600 DEFAULT CHARSET=utf8mb4

核心原因

这是MySQL优化器基于索引空间占用做出的最优选择,本质是为了减少IO开销:

  1. 索引结构差异
    InnoDB的主键索引是聚簇索引,每条记录包含整行数据+额外元数据(事务ID、回滚指针等,约13字节);而二级索引仅存储索引列值+主键值+少量元数据。
    在这个表中:
  • 聚簇索引单条记录大小:customer_id(2字节) + store_id(1字节) + 元数据(约13字节) = 约16字节
  • 二级索引idx_fk_store_id单条记录大小:store_id(1字节) + customer_id(2字节) + 少量元数据 = 约6字节
  1. 优化器的选择逻辑
    当执行count(customer_id)时,因为customer_id是主键(自带非空约束),统计逻辑等价于count(*)——只需遍历索引统计非空行数即可。此时优化器会优先选择体积最小的索引,因为更小的索引意味着需要读取的数据页更少,IO成本更低。这里二级索引idx_fk_store_id的整体空间远小于聚簇索引,所以被优化器选中。

InnoDB不像MyISAM会维护内置的行数统计,所有count操作都需要遍历索引完成,优化器的核心目标就是选择成本最低的执行路径。

内容的提问来源于stack exchange,提问作者Joseph Needham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:06:27