索引选择性低(如性别字段)易致全表扫描,因优化器认为回表开销大于遍历全表;选择性=COUNT(DISTINCT col)/COUNT(*),低于0.05~0.1时B+树索引常失效;需结合最左前缀、NULL处理、覆盖索引及EXPLAIN综合判断。

索引选择性低会导致全表扫描
当 WHERE 条件列的选择性很低(比如性别字段只有 '男'/'女' 两种值),MySQL 优化器很可能放弃使用该索引,直接走全表扫描。因为回表或扫描索引本身开销可能比遍历整张表还大。
- 选择性 =
COUNT(DISTINCT column) / COUNT(*),越接近 1 越好(如用户邮箱) - 低于 0.05~0.1 时,B+ 树索引通常失效(具体阈值受数据量、行大小、存储引擎影响)
- 用
EXPLAIN查看type字段:若为ALL或index,说明没走有效索引
联合索引的最左前缀原则直接影响选择性判断
MySQL 只能利用联合索引的连续前缀部分。即使 (a, b, c) 中 a 选择性差,但 (a, b) 组合选择性高,查询 WHERE a = ? AND b = ? 仍可高效命中索引。
- 避免把低选择性字段放在联合索引最左侧(如
(status, user_id)中status只有 3 个值) - 高频等值查询字段优先靠左;范围查询(
>,BETWEEN)字段必须放最右,否则右侧字段无法被索引使用 - 用
SHOW INDEX FROM table_name确认索引定义顺序,别只看CREATE INDEX语句写法
NULL 值会破坏索引选择性统计准确性
MySQL 的 ANALYZE TABLE 在统计列基数(Cardinality)时,对含大量 NULL 的列可能严重低估实际区分度,导致优化器误判索引价值。
淘宝互刷平台刷信誉源码主要特性:1、系统采用国内著名CMS内核做为基础模块化开发,继承CMS原有强大功能之外,同时拓展任务模块、快递单模块、会员模块、信用评价模块等多个相关模块,支持生成HTML静态和动态ASP,有效的提高了系统的性能,不仅减轻服务器的负载提高搜索收录率,增加网站收录。2、系统主要由淘宝任务、天猫任务、京东任务、阿里任务、拼多多任务、收藏任务、流量任务、快递单生成与查询系统、信用评
- 执行
SELECT COUNT(*), COUNT(column), COUNT(DISTINCT column) FROM table对比真实选择性 - 若列允许
NULL且占比高,考虑改用默认值(如'unknown')替代,或在查询中显式排除:WHERE column IS NOT NULL AND column = ? -
innodb_stats_persistent = ON+ 定期ANALYZE TABLE可缓解统计偏差,但无法根治NULL干扰
覆盖索引能绕过选择性瓶颈提升效率
即使筛选字段选择性低,只要查询所需所有字段都在索引中(即覆盖索引),MySQL 就无需回表,此时哪怕走 index 类型扫描,性能也远好于全表扫描。
- 例如表有
(status, create_time, id)联合索引,查询SELECT id FROM t WHERE status = 'draft'就是覆盖扫描 - 注意
SELECT *几乎不可能被覆盖,务必明确列出需要的字段 - 用
EXPLAIN检查Extra列是否含Using index,这是覆盖索引生效的关键标志
EXPLAIN SELECT id, create_time FROM orders WHERE status = 'shipped';索引选择性不是独立指标,它和查询模式、字段顺序、NULL 分布、是否覆盖紧密耦合。单独优化某列的选择性没意义,得结合
EXPLAIN 输出和实际慢查询场景一起看。









