mysql索引选择性=不同值个数/总行数,越接近1区分度越高、索引效率越好;user_id主键选择性≈1,status或gender等低区分度列选择性极低,优化器会据此评估索引有效性。

MySQL 索引的选择性(Selectivity)是指索引列中不同值的数量与该列总行数的比值,即:
选择性 = 不同值个数 / 总行数。
选择性越接近 1,说明该列区分度越高,索引效率通常越好;越接近 0,说明重复值越多,索引效果越差。影响选择性的关键因素不是人为“设置”的,而是由数据分布和索引结构共同决定的。
列值的唯一程度
这是最直接的影响因素。例如:
- 用户表中的
user_id(主键)几乎总是高选择性(≈1); - 订单表中的
status(如 'pending'/'shipped'/'cancelled')可能只有 3–5 个取值,选择性很低(比如 0.001); - 性别字段(
gender)通常只有 'M'/'F'/'O',选择性极低,单独建索引意义很小。
MySQL 优化器在生成执行计划时,会估算某个索引的选择性,若太低(如
数据分布是否均匀
即使某列整体唯一值不少,但若分布严重倾斜,也会降低实际选择性效果。例如:
- 日志表中
is_error字段:95% 是 0(正常),5% 是 1(错误);虽然有两个值,但选择性仅 0.05,且优化器对 0 的查询基本不会走索引; - 地区字段
country_code:中国、印度数据占 80%,其余 200 多个国家共占 20%,此时索引对“查小国”有效,但对“查中国”无效。
这种不均衡会让统计信息失真,进而影响执行计划稳定性。可通过 ANALYZE TABLE 更新统计信息,或用直方图(MySQL 8.0+)辅助优化器判断。
索引类型与长度限制
索引本身的设计会影响其“实际可分辨”的能力:
-
前缀索引(如
VARCHAR(255)列只索引前 10 个字符):会显著降低选择性,尤其当开头字符高度重复(如 URL 均以https://www.开头); -
复合索引顺序:
(a,b)的选择性取决于a的区分度 +a相同时b的区分度;若a本身低选择性,整个索引效果受限; -
NULL 值处理:MySQL 将所有
NULL视为相同值,大量 NULL 会拉低选择性估算(即使业务上它们代表不同含义)。
数据变更与统计信息滞后
选择性是动态的。以下情况会导致优化器“误判”:
- 大批量 INSERT/DELETE/UPDATE 后未执行
ANALYZE TABLE,统计信息过期; - 使用
innodb_stats_persistent=OFF(默认 OFF 在旧版本),采样随机,估算波动大; - 分区表中某些分区数据极少,但优化器按全局平均估算,造成局部选择性偏差。
可通过 SHOW INDEX FROM tbl 查看 Cardinality(基数)列,它是 MySQL 对不同值数量的估算值,虽非精确,但可作为选择性粗略参考。










