SQL 索引是怎么工作的?你会如何设计合理的索引?
索引B+树查询优化
考察意图
从「会写 SQL」进阶到「懂为什么慢」。考察索引结构直觉、最左前缀、选择性与写放大权衡。
回答框架
- 结构:InnoDB 聚簇索引 + 二级索引,B+树有序、适合范围。
- 何时建:高频过滤/连接/排序字段,且选择性够高。
- 怎么建:联合索引顺序、覆盖索引、避免函数包裹列。
- 代价:写入变慢、占空间;过多索引适得其反。
参考答案(口述版)
以 MySQL InnoDB 为例:数据按主键聚簇存放在 B+树叶子;二级索引叶子存「索引键 + 主键」,回表再取整行。
索引加速的本质是:用有序结构快速定位,避免全表扫描。范围查询、排序、分组也可能受益。
设计原则:
1. 先看慢查询:WHERE / JOIN / ORDER BY 高频字段
2. 选择性高的列更适合(区分度低如性别单独建索引价值小)
3. 联合索引遵循最左前缀:(a,b,c) 可支撑 a / a,b / a,b,c,难支撑只查 b
4. 能覆盖查询更好(覆盖索引避免回表)
5. 避免在索引列上套函数:DATE(created_at)=… 往往失效,改成范围条件
代价:每次写入要维护索引;索引太多会拖慢写入且优化器选错。实践是「用 explain 验证 + 监控慢查询」迭代,而不是一次性狂建。
关键词
B+树最左前缀选择性覆盖索引回表
面试官可能的追问
追问 1:什么是回表?如何减少?
二级索引找到主键后再回聚簇索引取整行。减少办法:覆盖索引(查询列都在索引里)、或把高频查询改成只取索引列。
追问 2:索引一定会变快吗?
不一定。结果集很大时优化器可能放弃索引;低选择性索引帮助有限;错误联合顺序等于没用。
常见踩坑
- 在低基数列上滥建单列索引
- 联合索引字段顺序拍脑袋
- 只看执行时间、不看 explain 的 type/rows/Extra
记忆锚点
索引是空间与写入换查询;联合索引顺序比「建了没有」更重要。