mysql索引的选择性是什么_mysql选择性优化建议

来源:这里教程网 时间:2026-02-28 20:47:13 作者:

什么是索引的选择性(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
或采样估算,避免全表扫描卡住。

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 列,后面全作废。

相关推荐