索引的选择性是指索引列不同值数量与总行数的比值,范围0–1;越接近1区分度越高,越接近0重复越多、效率越低;低选择性字段(如status、gender)不宜单独建索引,但可作为高选择性列后的联合索引后缀。

什么是索引的选择性(selectivity)
索引的选择性,指的是索引列中不同值的数量与该列总行数的比值,即 SELECT COUNT(DISTINCT col) / COUNT(*) FROM table。它的取值范围是 0 到 1:越接近 1,说明该列重复值越少,索引区分度越高;越接近 0,说明大量重复(比如性别、状态字段),索引效率越低。
为什么低选择性字段不适合单独建索引
MySQL 的 B+ 树索引在查找时依赖“跳过无关分支”的能力。如果 col 有 95% 的值都是 'active',那么查询 WHERE col = 'active' 仍需扫描全表约 95% 的叶子节点——此时走索引反而比全表扫描更慢(额外多了树遍历和回表开销)。
- 常见低选择性字段:
is_deleted、status(只有 2–3 个枚举值)、gender - MySQL 优化器通常会拒绝使用这类索引,执行计划里
key字段为NULL,type是ALL - 即使强制用
FORCE INDEX,实际性能往往更差
如何判断和测量某列的选择性
别只看直觉,用 SQL 算出来最准。注意:对大表要加 LIMIT 或采样估算,避免全表扫描卡住。
IEStore是一款B2C独立网上商店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。IEStore网上商店系统不仅在产品功能、稳定性、安全性和SEO支持(搜索引擎优化)等方面具有在同类产品领先地位,重要的是在功能架构上、操作上符合国际化标准,成为国际化电子商务的最佳软件选择之一。功能概要国际化标准IEStore网上商店系统是一个带有多国
SELECT COUNT(*) AS total, COUNT(DISTINCT user_id) AS distinct_uid, COUNT(DISTINCT email) AS distinct_email, ROUND(COUNT(DISTINCT email) / COUNT(*), 4) AS email_selectivity FROM users;
- email 选择性 ≈ 1.0?适合建唯一索引
- user_id 是主键,天然 1.0,无需额外判断
- 如果
email_selectivity (即 1%),基本可认为不适合作为独立索引首列 - 注意 NULL 值是否参与计算:
COUNT(DISTINCT col)默认忽略 NULL,但业务上 NULL 可能代表一类有效状态
低选择性字段怎么用索引才有效
单独建没用,但组合起来可能很关键。核心思路是:让低选择性字段作为联合索引的「后缀」,前面必须接高选择性列,且查询条件要满足最左前缀匹配。
- 错误写法:
INDEX(status, created_at)→ 查询WHERE status = 'draft'仍走不到索引 - 正确写法:
INDEX(user_id, status)→ 查询WHERE user_id = 123 AND status = 'draft'可高效定位 - 再优化:
INDEX(user_id, status, updated_at)→ 支持覆盖查询,避免回表 - 注意顺序:高选择性列必须在前,否则索引失效;
status在前、user_id在后,等于白建
真正容易被忽略的是:联合索引的“有效长度”取决于 WHERE 中连续出现的最左列数。哪怕你建了 5 列的索引,只要 WHERE 缺了第 2 列,后面全作废。









