大白话聊MySQL覆盖索引

目录

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解 线程池 请看: 线程池:从入门到精通,只需一杯咖啡的时间

其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏(已完结)】...等

如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力

✨更多文章请看个人主页: 码熔burning

一、什么是覆盖索引?

想象一下,你要查一本很厚的书 📖(数据库表)里的几条信息。

  1. 普通索引(没覆盖):就像书的目录(索引)。你先在目录里找到你要查的章节 🔍(比如按年龄查人),目录告诉你这个章节在第几页(数据行的位置)。然后,你得翻到那一页 📄(回到主表数据),才能看到完整的章节内容(比如这个人的姓名、邮箱等)。这个"翻到具体页码再去找内容"的动作,就有点像数据库里的"回表" 🏃💨。

  2. 覆盖索引:还是查书。但这次,你要查的信息(比如姓名和年龄),恰好在那个目录页上就直接写清楚了 ✨!你一看目录,哦,张三,30岁,李四,25岁... 你根本不需要再翻到书的正文页去找了,目录本身就"覆盖"了你所有需要的信息 ✅。

所以,覆盖索引就是一个包含了查询所需所有字段的索引 。当数据库发现可以用这个索引直接满足你的查询(包括 SELECT 出来的字段、WHERE 条件里的字段),它就只读取这个索引 🗂️,而不去读取实际的数据行,从而避免了"回表"操作。

二、使用了覆盖索引 vs 没使用覆盖索引的区别

特点 没使用覆盖索引 (需要回表 ↪️) 使用了覆盖索引 (不需要回表 👍)
查询过程 1. 通过索引找到主键ID。 2. 拿着主键ID去主表里,把完整的数据行捞出来 🏃💨。 3. 从完整数据行里提取你 SELECT 的字段。 1. 通过索引找到匹配的行。 2. 索引里已经包含了你 SELECT 的所有字段,直接从索引返回结果 ✅。
数据读取 需要读取 索引文件 🗂️ + 数据文件 📄 只需要读取索引文件 🗂️
I/O 操作 更多(至少两次磁盘/内存查找) 更少(一次索引查找)
性能 相对较慢 🐢 相对较快 🚀
大白话 查目录找到页码,再翻到那一页看详细内容。 查目录,发现目录上直接就有你要的所有信息,不用翻页了。
EXPLAIN Extra没有 Using index Extra会显示 Using index 👀

三、例子说明

假设我们有个 users 表 👤:

sql 复制代码
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50),
  age INT,
  email VARCHAR(100),
  INDEX idx_age (age) -- 普通索引,只包含 age 和 主键 id
);

情况一:没使用覆盖索引 🐢

查询:SELECT name, email FROM users WHERE age = 30;

过程:

  1. MySQL 使用 idx_age 索引,快速找到所有 age = 30 的行的主键 id
  2. 对于找到的每一个 id,MySQL 必须回到 users 表(聚簇索引)中,根据 id 找到完整的数据行 🏃💨。
  3. 从完整的数据行中提取 nameemail 字段。
  4. 这里发生了"回表" ↪️,因为 idx_age 索引里只有 ageid,没有 nameemail

情况二:使用覆盖索引 🚀

我们创建一个覆盖索引:

sql 复制代码
-- 先删除旧索引 (如果存在)
-- DROP INDEX idx_age ON users;

-- 创建覆盖索引,包含 WHERE 条件列和 SELECT 查询列
CREATE INDEX idx_age_name_email ON users (age, name, email);

查询:SELECT name, email FROM users WHERE age = 30;

过程:

  1. MySQL 使用 idx_age_name_email 索引。这个索引的叶子节点存储了 age, name, email (以及主键 id)。
  2. 它在索引中找到 age = 30 的条目。
  3. 因为索引里已经包含了 nameemail 这两个查询需要的字段 ✨,MySQL 直接从索引中读取 nameemail 并返回。
  4. 不需要 再根据主键 id 去主表里查找数据了 ✅。避免了"回表"。

四、总结

  • 覆盖索引就像一个信息更全的"目录" 📖,让数据库可以直接从目录(索引)里拿到所有需要的数据,不用再费劲去翻正文(主表数据)。
  • 主要好处是减少了 I/O 操作 (尤其是磁盘 I/O),避免了"回表",从而显著提高查询性能 🎉。
  • 判断是否用上了覆盖索引,最直接的方法是看 EXPLAIN 分析结果的 Extra 列是否包含 Using index 👀。

当然,创建覆盖索引也有代价 🤔,比如索引会占用更多存储空间 💾,并且在插入、更新、删除数据时,维护索引的成本也会增加。所以需要根据实际的查询场景权衡利弊 ⚖️。

相关推荐
小陈工2 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
0xDevNull6 小时前
MySQL数据冷热分离详解
后端·mysql
科技小花7 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸7 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain7 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希7 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神7 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员8 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java8 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿8 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb