6.什么是聚簇索引什么是非聚簇索引?
在 InnoDB 里,聚簇索引一般指主键索引,它的 B+ 树叶子节点存的是完整的一行数据,所以通过主键查询时,找到叶子节点就能拿到整行记录。
非聚簇索引也叫二级索引,比如普通索引、联合索引。它的叶子节点不存完整行数据,而是存索引字段和对应的主键值。所以通过二级索引查询时,如果要查的字段不在这个索引里,就需要先查到主键,再根据主键去聚簇索引中查完整数据,这个过程叫回表。
所以简单来说,聚簇索引叶子节点存整行数据,非聚簇索引叶子节点存主键值。聚簇索引通常只有一个,非聚簇索引可以有多个。
回表查询主要发生在 InnoDB 的二级索引查询中。
7. 知道什么是回表查询吗?
因为 InnoDB 的二级索引叶子节点存的不是完整行数据,而是索引字段和对应的主键值。所以当我们通过二级索引查数据时,如果查询的字段不在这个二级索引里,MySQL 就需要先通过二级索引找到主键 id,再根据这个主键 id 去聚簇索引里查完整行数据,这个过程就叫回表。如果查询的字段都在这个二级索引里,就不需要再回到聚簇索引查完整数据,这种情况就是覆盖索引。
8. 知道什么叫覆盖索引吗?
覆盖索引是指 SQL 查询需要的字段都包含在当前使用的索引中,MySQL 可以直接从索引中返回结果,不需要再回表查询完整行数据。
在 InnoDB 中,二级索引叶子节点保存的是索引列和主键值,所以如果查询字段都能从二级索引中拿到,就可以避免回表,提高查询效率。
9. MySQL超大分页怎么处理?
MySQL 超大分页慢,主要是因为 limit offset, size 在 offset 很大时,需要扫描并跳过大量记录,只返回最后的 size 条,所以性能会下降。
优化上,第一种可以使用覆盖索引加延迟关联,先通过索引查出目标页的主键 id,再根据 id 回表查询完整数据,减少扫描整行数据的成本。
第二种是游标分页,记录上一页最后一条记录的 id 或排序字段,下次查询时通过 where id > last_id limit size 查询,避免大 offset 扫描。
10. 索引创建原则有哪些?
索引创建我一般会从几个方面考虑。
首先不是所有表都需要建索引,通常是数据量比较大、查询比较频繁的表才有明显收益。
其次,索引一般建在 where 查询条件、join 关联字段、order by 排序字段、group by 分组字段上。
字段选择上,优先选择区分度高的字段,比如用户 id、手机号、订单号;像性别、状态这种区分度低的字段,不适合单独建索引,可以放在联合索引后面。
如果一个 SQL 经常按多个字段查询,可以考虑建立联合索引,并注意最左前缀原则。同时如果查询字段都在索引中,还可以形成覆盖索引,避免回表。
对于比较长的字符串字段,可以考虑使用前缀索引。
最后索引不是越多越好,索引会占用空间,也会影响增删改性能。
11.最左前缀原则是什么?
联合索引遵循最左前缀原则,也就是查询条件要尽量从联合索引的最左字段开始连续匹配。如果中间跳过字段,后面的字段一般就不能很好地利用索引。并且遇到范围查询后,后面的字段通常也不能继续用于索引定位。
12. 什么情况下索引会失效?
索引失效常见情况有:
- 联合索引没有遵循最左前缀原则;联合索引中遇到范围查询后,右边的字段通常不能继续用于索引定位。
like模糊查询时%放在最前面,比如like '%abc'。- 在索引字段上使用函数、运算,或者发生隐式类型转换。
- 使用
or时,如果两边字段不是都有索引,也可能导致索引失效。 - 查询返回的数据量太大时,优化器可能认为全表扫描更划算,也不会走索引。