索引选型关键在选择性与类型匹配:高选择性字段(>0.1)优先建b+树索引,复合索引需高选择性列在前;b+树要求最左前缀匹配,避免函数操作;全文、json、地理空间等场景应换用fulltext、生成列索引、spatial等专用索引;覆盖索引可避免回表,主键越短二级索引越高效。

索引选得对不对,直接决定查询快不快。核心就两点:选对类型、看准选择性。
先看选择性:高选择性字段优先建索引
选择性 = 唯一值数量 / 总行数。越接近1越好,比如用户ID、订单号通常接近1;而性别、状态这类只有几个取值的字段,选择性可能低于0.05,单独建B+树索引往往无效。
- 经验阈值:选择性 > 0.1 才值得为单列建普通索引
- 复合索引要按“高选择性列在前”排序,比如 (user_id, status) 比 (status, user_id) 更有效
- 用 SELECT COUNT(DISTINCT col)/COUNT(*) FROM table 快速估算选择性
B+树索引适用场景与限制
MySQL默认索引类型,支持等值、范围、ORDER BY、GROUP BY,但有隐含要求:
- 最左前缀匹配:WHERE a=1 AND b>10 可用 (a,b),但 WHERE b>10 就用不上
- 跳过中间列会断链:(a,b,c) 索引中,WHERE a=1 AND c=3 无法利用c,除非b也有确定值或范围
- 避免在索引列上做计算或函数:WHERE YEAR(create_time)=2024 会让索引失效,应改写为 create_time BETWEEN '2024-01-01' AND '2024-12-31'
什么时候考虑其他索引类型
B+树不是万能解,不同场景换类型更高效:
- 全文检索:用 FULLTEXT 索引配合 MATCH...AGAINST,比 LIKE '%关键词%' 快得多
- JSON字段路径查询:MySQL 8.0+ 支持生成列 + 虚拟索引,如 ALTER TABLE t ADD COLUMN j_name VARCHAR(64) AS (jdoc->>'$.name'), INDEX idx_jname (j_name)
- 地理空间查询:POINT 类型配 SPATIAL 索引,用于 ST_Contains、ST_Distance 等函数
- 超长字符串前缀区分:VARCHAR(1000) 不必全索引,可建前缀索引 index(col(100)),但需验证前100字符的选择性是否足够
别忽略覆盖索引和聚簇索引特性
索引本身能返回所有需要字段,就不回表——这就是覆盖索引的价值。InnoDB主键即聚簇索引,直接影响二级索引结构:
- 二级索引叶子节点存的是主键值,不是整行数据;所以主键越短(如 BIGINT 优于 VARCHAR(32)),二级索引越小、越快
- SELECT id, name FROM user WHERE name='Alice',若 (name) 索引存在,且 name 是 VARCHAR,但 id 是主键,则该查询可被 (name) 索引覆盖(因为二级索引自带主键)
- 用 EXPLAIN 查看 Extra 列是否含 "Using index",确认是否命中覆盖










