一、什么是回表查询?

这先要从InnoDB的索引实现说起,InnoDB有两大类索引:

聚集索引(clustered index)

普通索引(secondary index)

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

InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:

(1)如果表定义了PK,则PK就是聚集索引;

(2)如果表没有定义PK,则第一个not NULL unique列是聚集索引;

(3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引;

所以PK查询非常快,直接定位行记录。

InnoDB普通索引的叶子节点存储主键值。

注意,不是存储行记录头指针,MyISAM的索引叶子节点存储记录指针。

举个栗子,不妨设有表:

t(id PK, name KEY, sex, flag);

id是聚集索引,name是普通索引。

表中有四条记录:

该聚集索引和普通索引如图:

(1)id为PK,聚集索引,叶子节点存储行记录;

(2)name为KEY,普通索引,叶子节点存储PK值,即id;

如图可知主键索引从根节点开始利用页目录通过二分法查找某个索引页,由于索引是有序的,所以在数据页中同样利用二分法查询指定记录。

普通索引和主键索引一样是棵B+树,不过普通索引的记录和页按照某个非主键列的值排序,叶子节点保存的不是完整数据,而是某个非主键列和主键,普通索引的非叶结点保存的是非主键列和页号。

(重点)一个 SQL 只能利用到复合索引中的其中一列进行范围查询,因为B+树的每个叶子节点有一个指针指向下一个节点,把某一索引列的所有的叶子节点串在了一起,只能根据单列的叶子节点进行范围查询,这就是复合索引中只能有其中一列使用索引进行范围查询的原理。

既然从普通索引无法直接定位行记录,那普通索引的查询过程是怎么样的呢?

(重点)通常情况下,需要先遍历普通索引的B+树获得聚集索引主键id,然后遍历聚集索引的B+树获得行记录的对应的值。

B+树的每个叶子节点有一个指针指向下一个节点,把所有的叶子节点串在了一起,这就是范围查询使用索引的的原理。

如下图所示流程:

如粉红色路径,需要扫码两遍索引树:

(1)先通过普通索引定位到主键值id=5;

(2)在通过聚集索引定位到行记录;

(重点)这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

二、什么是索引覆盖(Covering index)?

explain查询计划优化章节,即explain的输出结果Extra字段为Using index时,能够触发索引覆盖。

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

三、如何实现索引覆盖?

常见的方法是:将被查询的字段,建立到联合索引里去。

仍是《迅猛定位低效SQL》中的例子:

第一个SQL语句:

select id,name from user where name='shenjian';

能够命中name索引,索引叶子节点存储了主键id,通过name的索引树即可获取id和name,无需回表,符合索引覆盖,效率较高。

Extra:Using index。

第二个SQL语句:

能够命中name索引,索引叶子节点存储了主键id,但sex字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过id值扫描聚集索引获取sex字段,效率会降低。

Extra:Using index condition。

如果把(name)单列索引升级为联合索引(name, sex)就不同了。

可以看到:

select id,name ... where name='shenjian';

select id,name,sex ... where name='shenjian';

都能够命中索引覆盖,无需回表。

画外音,Extra:Using index。

四、哪些场景可以利用索引覆盖来优化SQL?

场景1:全表count查询优化

原表为:

user(PK id, name, sex);

直接:

select count(name) from user;

不能利用索引覆盖。

添加索引:

alter table user add key(name);

就能够利用索引覆盖提效。

场景2:列查询回表优化

select id,name,sex ... where name='shenjian';

这个例子不再赘述,将单列索引(name)升级为联合索引(name, sex),即可避免回表。

场景3:分页查询

select id,name,sex ... order by name limit 500,100;

将单列索引(name)升级为联合索引(name, sex),也可以避免回表。

来源:

mysql联合索引查找过程_(MYSQL)回表查询原理,利用联合索引实现索引覆盖相关推荐

  1. MySQL数据库(四):多表查询、视图、事务、索引、函数、Go连接MySQL

    MySQL数据库:视图.事务.索引.函数.Go连接MySQL 1.1 目录 文章目录 1.1 目录 1.2 多表查询分类 1.2.1 内连接[inner join] 1.2.2 左外连接[left j ...

  2. mysql查询回表什么意思_什么是MYSQL回表查询

    select id,name where name='shenjian' select id,name,sex where name='shenjian' 多查询了一个属性,为何检索过程完全不同? 什 ...

  3. mysql 回表查询优化_MySQL优化:如何避免回表查询?什么是索引覆盖?

    转自:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651962609&idx=1&sn=46e59691257 ...

  4. 如何避免mysql回表查询_mysql如何避免回表查询

    <迅猛定位低效SQL?>留了一个尾巴: select id,name where name='shenjian' select id,name,sexwhere name='shenjia ...

  5. 什么是回表查询?如何避免回表查询?

    我们在索引中,有一种叫做聚集索引和非聚集索引的索引类型. 在聚集索引中,B+树上会存储这一行的全部数据,但是非聚集索引只会存储该列对应的值和相应行的主键. 是不是聚集索引的定义与主键索引很像? 其实就 ...

  6. mysql回表什么意思_什么是MYSQL回表查询

    select id,name where name='shenjian' select id,name,sex where name='shenjian' 多查询了一个属性,为何检索过程完全不同? 什 ...

  7. mysql回表什么意思_什么是Mysql的回表查询?聊一聊

    要说回表查询,先要从InnoDB的索引实现说起.InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Secondary Index). InnoDB的聚集索引 ...

  8. mysql 回表查询优化_MySQL中的回表查询与索引覆盖:一次百万级别分页查询使用Limit 从90秒到0.6毫秒的优化...

    这里写目录标题 事故现场 解决方案 提到的"回表查询" InnoDB的索引 什么是回表查询 怎么优化回表查询 事故现场 数据库使用的MySQL,有一个日志表,需要进行分页查询,于是 ...

  9. mysql非聚集索引区间查询_mysql的聚集索引和非聚集索引,回表查询,索引覆盖,最左前缀原则略解...

    什么是聚集索引和非聚集索引 我们知道 Mysql 底层是用 B+ 树来存储索引的,且数据都存在叶子节点.对于 InnoDB 来说,它的主键索引和行记录是存储在一起的,因此叫做聚集索引(clustere ...

最新文章

  1. 进程间通信之命名管道
  2. Q新闻丨MongoDB更换开源协议;Redis 5.0、Angular 7.0发布
  3. 这里有一份面筋请查收(七)
  4. Java枚举:您拥有优雅,优雅和力量,这就是我所爱!
  5. 如何在windows机器上安装apache ab
  6. 程序包android.support.annotation不存在_efcore技巧贴也许有你不知道的使用技巧
  7. hibernate mysql 配置文件_hibernate 框架的配置文件和映射文件以及详解
  8. MsSQL ——模拟limit
  9. 揭秘InputFormat:掌控Map Reduce任务执行的利器
  10. 机器学习——神经网络(四):BP神经网络
  11. C#做一年小孩做一个口算题生成器
  12. 戴尔t620服务器装系统2008驱动,dell服务器H310\H710阵列卡驱动
  13. 揭开 Java 注解的神秘面纱
  14. Java制作一个简单地小游戏
  15. java毕业生设计养老机构服务信息管理计算机源码+系统+mysql+调试部署+lw
  16. 数学分析:数项级数的概念
  17. (附源码)SSM校园一卡通管理系统JAVA计算机毕业设计项目
  18. 利用JAVA实现2+22+222+2222+22222的问题
  19. dr.oracle素颜霜好用吗,什么牌子的素颜霜保湿效果好呢?好用的素颜霜让你的皮肤越来越好...
  20. 华为设备配置3A之telent登陆

热门文章

  1. python unix时间戳格式化输出_python正常时间和unix时间戳相互转换的方法
  2. java css隔行变色_JS+CSS实现Li列表隔行换色效果的方法
  3. 前瞻:Spring 6.0将停止支持Freemarker和JSP
  4. 每日一皮:QA一来,大家都要靠边站!
  5. 从业务出发,来谈谈策略模式,清爽的飞起~
  6. 面了一把Java P6 岗,一个问题就干趴下了!
  7. 面试官:说说 Java 中的 Unsafe 和 CAS
  8. 推荐一款最好用Mysql数据库客户端
  9. 如何使用Mybatis的拦截器实现数据加密与解密
  10. mysql5.7修改连接数_Mysql 5.7 centos 7.2 修改最大连接数 无效 2018-03-08