网站首页 > 技术文章 正文
什么是回表查询
小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键、聚集索引、辅助索引,简单回顾下,聚集索引的叶子节点包含完整的行数据,而非聚集索引的叶子节点存储的是每行数据的辅助索引键 + 该行数据对应的聚集索引键(主键值)。
假设有张 user 表,包含 id(主键),name,age(普通索引)三列,有如下数据:
id name age
1 Jack 18
7 Alice 28
10 Bob 38
20 Carry 48
画一个比较简单比较容易懂的图来看下聚集索引和辅助索引:
- 聚集索引:
- 辅助索引(age):
如果查询条件为主键,则只需扫描一次聚集索引的 B+ 树即可定位到要查找的行记录。举个例子:
select * from user where id = 7;
查找过程如图中绿色所示:
如果查询条件为普通索引(辅助索引) age,则需要先查一遍辅助索引 B+ 树,根据辅助索引键得到对应的聚集索引键,然后再去聚集索引 B+ 树中查找到对应的行记录。举个例子:
select * from user where age = 28;
上述 select * 等同于 select id, age, name 对吧,id 是主键索引,age 是普通索引,而 name 并不存在于 age 索引的 B+ 树上,所以通过 age 索引查询到 id 和 age 的值之后,还需要去聚集索引上才能查到 name 的值。
如图所示,第一步,查 age 辅助索引:
第二步,查聚集索引:
这就是所谓的回表查询,因为需要扫描两次索引 B+ 树,所以很显然它的性能较扫一遍索引树更低。
什么是覆盖索引
覆盖索引的目的就是避免发生回表查询,也就是说,通过覆盖索引,只需要扫描一次 B+ 树即可获得所需的行记录。
如何实现覆盖索引
上文解释过,下面这个 SQL 语句需要查询两次 B+ 树:
select * from user where age = 28;
我们将其稍作修改,使其只需要查询一次 B+ 树:
select id, age from user where age = 28;
之前我们的返回结果是整个行记录,现在我们的返回结果只需要 id 和 age。
id 是什么?主键索引(聚集索引),age 是什么?普通索引(辅助索引),age 索引的 B+ 树的叶子节点存储的是什么?辅助索引键 + 对应的聚集索引键
所以这条 SQL 语句只需要扫描一次 age 索引的 B+ 树就行了
这样,结合这个例子,不知道各位有没有受到启发,如何实现覆盖索引拒绝回表查询呢?
答:联合索引。
我们把 age,name 设置为联合索引:
create index idx_age_name on user(`age`,`name`);
此时 age 和 name 作为辅助索引键都在同一棵辅助索引的 B+ 树上,所以只需扫描一次这个组合索引的 B+ 树即可获取到 id、age 和 name,这就是实现了索引覆盖
覆盖索引的常见使用场景
在下面三个场景中,可以使用覆盖索引来进行优化 SQL 语句:
1)列查询回表优化(如上面讲的例子,将单列索引 age 升级为联合索引(age, name))
2)全表 count 查询
举个例子,假设 user 表中现在只有一个索引即主键 id:
select count(age) from user;
可以用 explain 分析下这条语句,如果 Extra 字段为 Using index 时,就表示触发索引覆盖:
显然现在是没有触发覆盖索引的,我们来优化下:将 age 列设置为索引 create index idx_age on user(age),这样只需要查一遍 age 索引的 B+ 树即可得到结果:
3)分页查询
select id, age, name from user order by username limit 500, 100;
对于这条 SQL,因为 name 字段不是索引,所以在分页查询需要进行回表查询。
Using filesort 表示没有使用索引的排序,或者说表示在索引之外,需要额外进行外部的排序动作。看到这个字段就应该意识到你需要对这条 SQL 进行优化了。
使用索引覆盖优化:将 (age, name) 设置为联合索引,这样只需要查一遍 (age, name) 联合索引的 B+ 树即可得到结果。
猜你喜欢
- 2024-10-22 Oracle SQL 查询排序 oracle的排序
- 2024-10-22 Oracle查询语句,你知道几个?(下)
- 2024-10-22 Oracle连接查询有哪些写法 oracle数据库连表查询
- 2024-10-22 Oracle的基本查询语法 oracle常用查询
- 2024-10-22 工作中你会用几种方式来查看oracle执行计划呢?
- 2024-10-22 oracle虚拟索引如何查询大小? oracle查看虚拟列
- 2024-10-22 Oracle按时间范围查询sql分享 oracle按照时间查询
- 2024-10-22 Oracle 11G,实践操作,SQL分类,去重操作
- 2024-10-22 #干货推荐# Oracle_sql优化 #oracle sql优化一般从那几个方面入手
- 2024-10-22 【Oracle】多表联合查询超时问题排查
你 发表评论:
欢迎- 633℃几个Oracle空值处理函数 oracle处理null值的函数
- 626℃Oracle分析函数之Lag和Lead()使用
- 614℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 608℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 606℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 599℃【数据统计分析】详解Oracle分组函数之CUBE
- 588℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 574℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- oracle 19cOCM认证有哪些内容(oracle认证ocm月薪)
- Oracle新出AI课程认证,转型要持续学习
- oracle 表的查询join顺序,可能会影响查询效率
- Oracle DatabaseAmazon Web Services正式可用,Oracle数据库上云更容易了
- Oracle 19.28 RU 升级最佳实践指南
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
- 如何主导设计一个亿级高并发系统架构-数据存储架构(三)
- Java 后端开发必看!工厂设计模式轻松拿捏
- ORA-00600 「25027」 「x」报错(抱错孩子电视剧 爸爸是武术 另一个爸爸是画家)
- 新项目终于用上了jdk24(jdk新建项目)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (58)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)