你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。
文章可能会比较长,主要解析的非常详解,或涉及一些底层知识,供面试高阶难度用。可以根据自己实际理解情况合理取舍阅读
查询过程:当执行查询时,MySQL 通过索引定位到符合条件的记录位置(比如根据索引列找到一条记录的主键)。
回表查找数据:然后,MySQL 会根据这些主键值去数据表中查找完整的记录,拿到完整的字段值。
查询的字段不在索引中
如果查询的字段不在索引中,那么 MySQL 会先通过索引找到符合条件的行,然后回到原表中去查询其他字段的值。这是最常见的回表情况。
假设有一个 users 表,如下所示:
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
age INT
);
假设我们创建了一个针对 name 字段的索引:
CREATE INDEX idx_name ON users(name);
如果你查询 name 和 email 字段:
SELECT name, email FROM users WHERE name = 'John';
在这个查询中,name 字段有索引,MySQL 会通过 idx_name 索引查找到符合条件的记录。但是因为 email 字段没有包含在索引中,MySQL 需要回表查询完整的 email 数据。
回表步骤:
MySQL 通过 idx_name 索引查找符合条件的 name = 'John' 的记录,假设找到了对应的 id。
然后,MySQL 通过 id 这个主键值回到原始的 users 表中查询 email 字段的值。
复合索引不覆盖查询字段
如果你使用的是复合索引(多个列组合的索引),但查询中所使用的字段没有完全覆盖索引,那么 MySQL 仍然会回表。
例子:
假设你创建了一个包含 name 和 age 的复合索引:
CREATE INDEX idx_name_age ON users(name, age);
然后执行如下查询:
SELECT name, email FROM users WHERE name = 'John' AND age = 25;
这个查询中,name 和 age 都包含在 idx_name_age 复合索引中,所以 MySQL 可以快速定位到符合条件的记录。然而,由于查询的字段 email 不在索引中,MySQL 仍然需要回表查询。
查询条件不完全匹配索引
如果查询条件只包含索引的一部分列,MySQL 可能无法直接通过索引查询到所有需要的数据,依然需要回表。
例子:
假设你有以下复合索引:
CREATE INDEX idx_name_age ON users(name, age);
然后执行如下查询:
SELECT name FROM users WHERE age = 25;
在这个查询中,索引是基于 (name, age) 组合的,但查询条件中只使用了 age 字段。因此,MySQL 只能通过索引的部分列来定位符合条件的记录,但由于查询结果中不包含 name 以外的其他列(例如 age),所以必须回表去读取完整的记录。
覆盖索引是指索引包含了查询所需的所有字段。在这种情况下,查询结果可以直接从索引中获取,而不需要回表,从而避免了回表带来的性能损失。
例子:
假设你只查询 name 和 email,并且 name 和 email 都在一个复合索引中:
CREATE INDEX idx_name_email ON users(name, email);
然后执行如下查询:
SELECT name, email FROM users WHERE name = 'John';
由于 name 和 email 都在 idx_name_email 索引中,查询可以通过索引直接返回结果,而不需要回表。
选择合适的索引列
在设计索引时,要确保索引尽可能覆盖常用的查询字段,避免在查询时出现需要回表的情况。
例子:
如果你经常按 name 和 email 查询,可以创建一个复合索引:
CREATE INDEX idx_name_email ON users(name, email);
避免不必要的查询字段
只查询需要的字段,尽量避免使用 SELECT *,这样可以减少回表的概率。
回表是当查询中的字段没有包含在索引中时,MySQL 在通过索引查找到符合条件的记录后,再次回到原始表中查询完整的数据。这会导致性能损失,因为需要额外的磁盘 I/O 操作。
为了避免回表,应该:
使用覆盖索引,即索引包含查询所需的所有字段。
精确选择索引列,确保查询条件能够完全利用索引。
避免不必要的字段查询,减少不必要的回表操作。
今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!