MySQL中的回表

在 MySQL 中,回表(Look Up)是指数据库执行查询时的一种操作模式,特别是在使用非聚簇索引(也称为二级索引或辅助索引)时。

当查询使用非聚簇索引时,索引中通常只包含部分列的信息,而完整的行数据则存储在聚簇索引(通常是主键索引)中。

因此,在查询过程中,MySQL 首先会使用非聚簇索引来查找匹配的行,但这通常只能得到这些行的主键值。

一旦 MySQL 通过非聚簇索引找到了主键值,它就需要“回”到聚簇索引中去查找与这些主键值相对应的完整行数据。这个过程就被称为回表。

回表操作涉及额外的磁盘 I/O 和 CPU 开销,因为每次都需要从磁盘读取数据页来获取完整的行记录。

回表通常发生在以下几种情况: 使用非聚簇索引进行查询,但查询结果需要返回不在该索引中的列。 执行范围查询或全表扫描时,如果需要获取完整行数据,即使使用了索引,也可能需要回表。

为了避免回表,可以使用覆盖索引(Covering Index)策略,即创建一个包含查询所需所有列的索引,这样查询可以直接从索引中获取所有需要的数据,而无需访问聚簇索引,从而提高查询效率。此外,MySQL 5.6 引入的 Multiple Range Read(MRR)优化器可以缓存多次随机访问的主键值,然后进行批量读取,减少回表带来的性能影响。

示例

假设我们有一个 employees 表,结构如下:

CREATE TABLE `employees` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `first_name` VARCHAR(45) NOT NULL,
  `last_name` VARCHAR(45) NOT NULL,
  `email` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `idx_email` (`email`)
);

在这个例子中,id 是聚簇索引(主键索引),而 email 是非聚簇索引。

回表示例

如果我们执行以下 SQL 查询:

SELECT id, first_name, last_name FROM employees WHERE email = 'zhangsan@example.com';

这里,MySQL 将首先使用 email 索引找到匹配的记录,但是 email 索引中不包含 first_name 和 last_name 字段。 因此,MySQL 必须回表,即根据 email 索引中找到的 id 值再次访问聚簇索引,以获取 first_name 和 last_name 的值。

避免回表示例

为了避免回表,我们可以创建一个覆盖索引,包括 email 以及 first_name 和 last_name 字段:

ALTER TABLE `employees`
ADD INDEX `idx_email_full` (`email`, `first_name`, `last_name`);

现在,如果我们再次运行相同的查询,MySQL 将能够直接从 idx_email_full 索引中获取所有需要的数据,无需回表。

SELECT id, first_name, last_name FROM employees WHERE email = 'john.doe@example.com';

这将显著提高查询效率,特别是当表非常大且数据分布在多个磁盘块上时。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇