提到什么是回表查询之前,不得不先解释一下InnoDB的索引。

InnoDB的索引

InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Secondary Index)

InnoDB聚集索引和普通索引有什么差异?有什么区别呢?

InnoDB的聚集索引

每行数据是存在InnoDB聚集索引的叶子节点上的,因此InnoDB必须要有且只有一个聚集索引,下面聚集索引的生成规则:

  • 如果表定义了PK(Primary Key,主键),那么PK就是聚集索引。
  • 如果表没有定义PK,则第一个NOT NULL UNIQUE的列就是聚集索引。
  • 否则InnoDB会另外创建一个隐藏的ROWID作为聚集索引。

这种机制使得基于PK的查询速度非常快,因为直接定位的行记录。

InnoDB普通索引

InnoDB普通索引的叶子节点存储主键值。想拿到行数据,还得去聚集索引中扫描索引树。
注意,不是存储行记录头指针,MyISAM的索引叶子节点存储记录指针。


什么是回表查询

下面举个例子解释:
假设有个表user(id PK,name,code),id是聚集索引,code是普通索引。表中有几条数据。

id name code -----
1 小明 AQ -----
4 小陈 DR -----
7 小红 CY -----
9 小刘 FP -----
那么两种索引的B+树索引就是如下图这样:

MySQL中的回表查询与索引覆盖:一次百万级别分页查询使用Limit 从90秒到0.6毫秒的优化_第1张图片
从普通索引无法直接定位行记录,那普通索引的查询过程是怎么样的呢?

例: select * from user where code = ‘CY’;

其查询过程在通常情况下是需要扫描两遍索引树的,这里的执行过程是这样的:

如带色的路径:

  • 第一遍先通过普通索引定位到主键值
  • 然后第二遍再通过聚集索引定位到具体行记录。

这就是所谓的回表查询,即先定位主键值,再根据主键值定位行记录,性能相对于只扫描一遍聚集索引树的性能要低一些。


怎么优化回表查询

那怎么样解决这个性能低的问题呢?这就涉及到一个概念---------覆盖索引

覆盖索引

覆盖索引就是是一种避免回表查询的优化策略。就是把所有需要查询的字段都放到普通索引中,这样普通索引查到的叶子结点(即上图中的黑色方框)中已经能够得到所需的所有字段,就不会再去聚集索引中再查询。

实现覆盖索引的方式

可分为两种:

第一种减少查询字段只查询缩影有的字段,例如在查询中,我们只查id字段(也就是主键字段),这样几百万条数据就不会回表查询,外层查询时只有50条数据去聚集索引里进行了查询。又如上面的user表 优化sql为不查询name字段。

例: select id,code from user where code = ‘CY’;

第二种方式就是修改表创建的索引,增加需要查询的字段,如上面user表,把name也加到索引中,设置(name,code)两个字段的联合索引 。

覆盖索引的定义与注意事项

如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。

要注意的是,不是所有类型的索引都可以成为覆盖索引的。因为覆盖索引必须要存储索引的列值,而哈希索引、空间索引和全文索引等都不存储索引列值,索引MySQL只能使用B-Tree索引做覆盖索引。

另外,当发起一个被索引覆盖的查询(索引覆盖查询)时,在explain(执行计划)的Extra列可以看到【Using Index】的信息。

覆盖索引的优点

1.索引条目通常远小于数据行的大小,因为覆盖索引只需要读取索引,极大地减少了数据的访问量。

2.索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多。

3.一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点。

4.由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询。

【一起去大厂系列】什么是回表查询?怎么优化回表查询?相关推荐

  1. Hive 分桶表原理及优化大表 join 实战

    一.什么是分桶表 分桶表,比普通表或者分区表有着更为细粒度的数据划分. 举个例子,每天产生的日志可以建立分区表,每个分区在 hdfs 上就是一个目录,这个目录下包含了当天的所有日志记录. 而分桶表,可 ...

  2. SQL Server 查询性能优化——堆表、碎片与索引(一)

    SQL Server在堆表中查询数据时,是不知道到底有多少数据行符合你所指定的查找条件,它将根据指定的查询条件把数据表的全部数据都查找一遍.如果有可采用的索引,SQL Server只需要在索引层级查找 ...

  3. SQL Server查询性能优化——堆表、碎片与索引(一)

    SQL Server在堆表中查询数据时,是不知道到底有多少数据行符合你所指定的查找条件,它将根据指定的查询条件把数据表的全部数据都查找 一遍.如果有可采用的索引,SQL Server只需要在索引层级查 ...

  4. 【一起去大厂系列】针对left join以及limit的两条优化小技巧

    记两则亲身经历的sql优化技巧: 一.主表数据不到100万,以下查询结果集约200左右,第一条sql执行效率为40ms,第二条为200ms,使用上面方法,其效率明显优于left join: sql1: ...

  5. 【一起去大厂系列】深入理解MySQL中where 1 = 1的用处

    首先,明白一个前提条件: where 1 = 1; --永远为真 也就是说: select * from student; 等同于: select * from student where 1 = 1 ...

  6. Blink中的维表join及优化

    我觉得本篇博客算是性能优化的一个补充,性能优化篇: Blink性能优化配置及原理 文章目录 双流john 维表join以及优化 维表join开启cache策略 缓存未命中 key Distribute ...

  7. sql语句用变量替换表名_使用内存优化表替换SQL临时表和表变量

    sql语句用变量替换表名 TempDB usage can be considered as a performance bottleneck for workloads that use SQL t ...

  8. 将一个基于磁盘的表迁移到SQL Server中的一个内存优化的表

    本文是微软的译文,对应的原文是:https://www.red-gate.com/simple-talk/sql/database-administration/migrating-disk-base ...

  9. 不懂就问系列,为什么别人能靠这份面试题宝典去大厂?(内附面试题答案)

    就目前的一线企业面试模式来讲,尤其是一面与二面都涉及到很深的Java基础功底及知识面,在面试前积极的准备面试,复习整个 Java 知识体系将变得非常重要,可以很负责任的说一句,复习准备的是否充分,将直 ...

最新文章

  1. iOS多设备分辨率适配
  2. 注册自定义HTTP Handlers
  3. java编程 内存_Java编程技术之浅析JVM内存
  4. Java课程设计和sql数据库_数据库SQLserver+java课程设计
  5. LeetCode问题7
  6. 64 ----平面与直线之间的位置关系、平面与直线之间的交角、两直线两平面的位置关系
  7. 力扣-559. N 叉树的最大深度
  8. 【经验贴】Java搭建一个以yy直播为主的直播聊天室
  9. 量化交易策略研发的三个层次
  10. Manjaro 开发环境配置和使用技巧
  11. 由C注释向C++注释转换简单实现
  12. 什么样的人才是幸福的?
  13. excel 数据透视表,笔记6,权亮
  14. Percona XtraDB Cluster(PXC)——架构原理
  15. 15个Python入门小程序,同事准时下班“小技巧”被我发现了
  16. codeforces 784-div4(感觉这个难度有点逆天,呼呼的做水题)
  17. gbase 导出_gbase 通过 gccli 命令客户端导出数据到文件
  18. Java开发环境搭建:eclipse安装和工程创建
  19. vue打包的文件加上版本号
  20. 设计模式:(策略模式)

热门文章

  1. go-zero:微服务框架
  2. 第四期直播分享预告-高薪offer指南
  3. 优化 Golang 分布式行情推送的性能瓶颈
  4. NAB 2019见闻:CAE视频编码与QoE
  5. LiveVideoStack线上交流分享 (十七) —— AV1编码器优化与实用落地演进之路
  6. 学习方法之01高效学习方程式,你的学习到底是哪里出了问题
  7. 指标统计:基于流计算 Oceanus(Flink) 实现实时 UVPV 统计
  8. 腾讯云数据库闪耀曼哈顿,CynosDB回馈开源社区
  9. ngx_conf_s
  10. linux shell trap的使用