面试通关特训营第三天 ✅

2024 - 12 - 26

大家好,我是正在努力掌握 MySQL 知识的技术搬砖人 K.N。
昨天刷了三道 B+ 树的问题,今天早上工作的时候又不断在写前端相关的东西,今天继续进行三道 MySQL ,突然感觉自己像是在两个完全不同的战场来回穿梭,不过学习 MySQL 的乐趣还是挺多的,尤其是研究索引和优化时,真的感觉在探索性能的极限。

今天面试特训营的三道题目,主题依旧围绕 MySQL 的索引优化:
1)MySQL 中的回表是什么?
2)MySQL 中使用索引一定有效吗?如何排查索引效果?
3)在 MySQL 中建索引时需要注意哪些事项?

以下是我的学习心得,有错误的话请各位大神多多指点!

MySQL 中的回表是什么?

回表其实是 MySQL 查询过程中的一种现象,通俗点说,就是在用二级索引查询时,因为二级索引只存储键值和主键,没法直接拿到完整数据,需要通过主键再次查询聚簇索引来获取数据。

举个例子,假设有一张用户表 user,有一个二级索引 email。当执行以下语句时:

tsx
复制代码
SELECT name FROM user WHERE email = 'test@example.com'
  • MySQL 先通过 email 索引找到对应的主键值;
  • 然后再根据主键去聚簇索引中查找完整的行数据,获取 name 字段。

这个“先查索引,再回到聚簇索引”的过程就是回表。它在小数据量时影响不明显,但在大表查询或高频次查询中,会带来额外的性能消耗。解决回表问题的一个常见方法是使用覆盖索引(即查询字段全在索引里),这样可以直接通过二级索引返回结果,避免回表。

MySQL 中使用索引一定有效吗?如何排查索引效果?

索引并不是万能的,有时候它甚至可能不被使用或者导致性能下降。常见的索引失效场景包括:

  • 条件不符合最左前缀原则,比如联合索引 (a, b),查询时跳过了 a;
  • 使用了函数或表达式,例如 WHERE LEFT(name, 3) = 'abc';
  • 对索引列做了隐式类型转换,比如 WHERE age = '18',而 age 是一个整数;
  • 查询条件范围过大,比如 WHERE age > 100;
  • 查询数据量太大时,MySQL 可能认为全表扫描更划算。

要排查索引效果,可以使用 EXPLAIN 分析执行计划。比如:

plain
复制代码
EXPLAIN SELECT name FROM user WHERE email = 'test@example.com';

重点关注 key、rows 和 Extra。如果 Extra 显示 Using where 或 Using filesort,说明查询性能可能存在问题。

另外,还可以用 SHOW STATUS LIKE 'Handler%' 查看查询过程中 MySQL 的索引使用情况。例如 Handler_read_key 表示通过索引读取的次数,Handler_read_rnd_next 表示全表扫描的次数。通过对比这些值,可以评估索引是否高效。

在 MySQL 中建索引时需要注意哪些事项?

建索引是一门艺术,做好了可以大幅提升性能,没做好可能白白浪费存储和资源。总结下来,有几个关键点需要注意:

  1. 根据查询需求设计索引:不要盲目创建索引,应该结合查询频率和条件来设计。比如经常用 WHERE status = ?,就需要给 status 建索引。
  2. 选择合适的字段顺序:联合索引 (a, b) 一定要优先把查询中使用最频繁的字段放在前面,比如 a 如果比 b 更常用于筛选,就让它排第一。
  3. 避免为低选择性字段建索引:比如 gender 这种只有两三个值的字段,建索引的效果很差,因为过滤效率低。
  4. 控制索引数量:索引会占用额外的存储空间,同时会影响插入、更新和删除操作的性能。一般来说,尽量只建最必要的索引。
  5. 考虑覆盖索引:如果查询的字段都能通过索引返回结果,避免回表,可以显著提高查询效率。
  6. 避免重复和冗余索引:比如同时建了 (a) 和 (a, b) 两个索引,其实前者是多余的。

建索引的时候,多用 EXPLAIN 和慢查询日志分析查询性能,确保索引是有价值的,而不是增加额外负担。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
KINNONG
下载 APP