文章目录
-
- [一、高频出现在 WHERE 条件中的字段](#一、高频出现在 WHERE 条件中的字段)
- [二、JOIN 关联查询中的关联字段(外键字段)](#二、JOIN 关联查询中的关联字段(外键字段))
- [三、ORDER BY / GROUP BY 后面的字段](#三、ORDER BY / GROUP BY 后面的字段)
- [四、区分度高的字段(Cardinality 大)](#四、区分度高的字段(Cardinality 大))
- 五、需要保证唯一性的业务字段
- 六、适合做「覆盖索引」的高频查询
- 反向补充:这些情况不建议建索引
- 新手建索引优先级参考
一、高频出现在 WHERE 条件中的字段
这是索引最核心、最常用的场景。
为什么适合
查询时,如果字段没有索引,就必须逐行扫描整张表(全表扫描);
有了索引,就能通过 B+ 树快速定位到符合条件的行,数据量越大提速越明显。
典型例子
- 业务中经常按「员工姓名」「邮箱」「部门ID」查员工信息,这些字段就适合建索引。
- 对应你的
employees表:department_id、job_id这类经常作为筛选条件的字段,建索引就是合理的。
重要补充
如果多个字段经常组合在一起做查询条件 ,优先建联合索引 ,而不是给每个字段单独建单列索引。
比如,经常用 name + age 筛选,建 idx_name_age(name, age) 的收益,远高于两个单列索引。
二、JOIN 关联查询中的关联字段(外键字段)
联表查询的关联字段,几乎是必建索引的场景。
为什么适合
两张表关联查询时
(比如 employees JOIN departments ON employees.department_id = departments.id),
如果关联字段没有索引,每次关联匹配都要做一次全表扫描,数据量上来后性能会极差。
典型例子
你的 employees 表里的 department_id、job_id、manager_id 都属于这类:
department_id关联部门表job_id关联职位表manager_id关联上级员工(自连接)
这也是为什么你这张表的这三个字段都已经建了索引,是非常标准的建法。
注意
关联字段的类型、长度、字符集必须完全一致 ,否则会触发隐式类型转换,导致索引失效。
三、ORDER BY / GROUP BY 后面的字段
排序 和 分组,是索引的第二大适用场景。
为什么适合
B+ 树索引本身就是排好序的结构:
ORDER BY:直接用索引的顺序输出,不用再做「文件排序(Using filesort)」,速度提升非常明显GROUP BY:索引有序,分组时不用再生成临时表(Using temporary),避免额外的内存/磁盘开销
典型例子
- 经常按「入职时间倒序」查询员工列表 →
hire_date适合建索引 - 经常按「部门分组统计人数」 →
department_id适合建索引
补充技巧
如果查询同时有 WHERE 和 ORDER BY,优先建联合索引 ,把 WHERE 字段放最左边,排序字段放后面,符合最左前缀原则,既能过滤又能排序。
比如:WHERE department_id = 10 ORDER BY hire_date
建 idx_dept_hire(department_id, hire_date)
四、区分度高的字段(Cardinality 大)
索引的效率,很大程度取决于字段的「区分度」。
为什么适合
区分度越高,索引一次能过滤掉的数据就越多,查询效率提升越明显;
反之,如果字段值大量重复,索引过滤不了几行,优化器会觉得还不如全表扫,直接放弃索引。
判断标准
看 SHOW INDEX 里的 Cardinality 值,值越接近表总行数,区分度越好。
- ✅ 适合:邮箱、工号、身份证号,几乎不重复,区分度拉满
- ❌ 不适合:性别、状态(只有 0/1 两种值)、是否删除等低基数字段
对应你的表
employee_id、email基数 107,和表总行数一致 → 区分度极好,建索引收益最高department_id基数 12 → 区分度一般,数据量小的时候还行,百万级数据下收益会很低
五、需要保证唯一性的业务字段
业务上要求不重复的字段,直接建唯一索引,一举两得。
为什么适合
- 数据约束:由数据库层面保证字段值不重复,比代码判断更可靠,能避免并发导致的重复数据
- 查询加速:唯一索引同时具备普通索引的所有加速能力,等值查询性能极高
典型例子
- 员工邮箱、工号、身份证号
- 对应你表里的
emp_email_uk,就是非常标准的唯一索引设计
六、适合做「覆盖索引」的高频查询
这是进阶优化场景,用得好性能提升非常显著。
为什么适合
如果一条查询要取的字段,在索引里就全部包含了,就不需要回表去聚簇索引里查完整数据,直接从二级索引里就能拿到结果,这就是覆盖索引,省去了回表的IO开销。
典型例子
业务高频执行:
sql
SELECT name, age
FROM employees
WHERE name = '张三';
建联合索引 idx_name_age(name, age),查询时直接从索引里取 name 和 age,完全不用回表,
性能接近主键查询。
反向补充:这些情况不建议建索引
知道什么时候建,也要知道什么时候别乱建:
- 数据量很小的表(几百几千行):全表扫描比走索引还快,建了反而浪费空间
- 写操作远多于读操作的表:增删改都要维护索引,会大幅拖慢写入性能
- 区分度极低的字段(如性别、状态):索引收益几乎为0
- 频繁更新的字段:索引维护成本很高
- 冗余、重复的索引 :比如你表里的
emp_emp_id_pk,和主键索引完全重复,纯纯浪费空间
新手建索引优先级参考
按重要性从高到低:
- 主键(自动创建,不用管)
- 业务唯一键 → 建唯一索引
- 所有 JOIN 关联字段 → 建普通索引
- 高频出现在 WHERE 中的字段 → 按需建单列/联合索引
- 经常排序、分组的字段 → 结合 WHERE 建联合索引
- 高频慢查询 → 用覆盖索引做专项优化