转自:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651962609&idx=1&sn=46e59691257188d33a91648640bcffa5&chksm=bd2d092d8a5a803baea59510259b28f0669dbb72b6a5e90a465205e9497e5173d13e3bb51b19&mpshare=1&scene=1&srcid=&sharer_sharetime=1564396837343&sharer_shareid=7cd5f6d8b77d171f90b241828891a85f&key=abd60b96b5d1f2e52ca45314fb2c95a67fad7a457fe265562eb51a1c026389d3f28c52359f96e920368ab44a5d08ebcbbe2ded474be2ba70731ed8b5dcc5dd68cc0eceb4989a74fb04e5055c78af8d38&ascene=1&uin=MTAwMjA4NTM0Mw%3D%3D&devicetype=Windows+7&version=62060739&lang=zh_CN&pass_ticket=tXA4xc7SZYamLpGZz5B6JwJa1ZRvZ4bRlmzFhXwEKeOfloPLulU0O80gsIQUiONb

正式讲解:

数据库表结构:

1 create table user(2 id int primary key,3 name varchar(20),4 sex varchar(5),5 index(name)6 )engine=innodb;

多查询了一个属性,为何检索过程完全不同?

什么是回表查询?

什么是索引覆盖?

如何实现索引覆盖?

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

这些,这是今天要分享的内容。

画外音:本文试验基于MySQL5.6-InnoDB。

一、什么是回表查询?

这先要从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, shenjian, m, A

3, zhangsan, m, A

5, lisi, m, A

9, wangwu, f, B

两个B+树索引分别如上图:

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

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

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

通常情况下,需要扫码两遍索引树。

例如:

是如何执行的呢?

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

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

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

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

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

额,楼主并没有在MySQL的官网找到这个概念。

画外音:治学严谨吧?

借用一下SQL-Server官网的说法。

MySQL官网,类似的说法出现在explain查询计划优化章节,即explain的输出结果Extra字段为Using index时,能够触发索引覆盖。

不管是SQL-Server官网,还是MySQL官网,都表达了:只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

三、如何实现索引覆盖?

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

仍是之前中的例子:

第一个SQL语句:

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

画外音,Extra:Using index。

第二个SQL语句:

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

画外音,Extra:Using index condition。

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

可以看到:

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

画外音,Extra:Using index。

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

场景1:全表count查询优化

原表为:

user(PK id, name, sex);

直接:

不能利用索引覆盖。

添加索引:

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

场景2:列查询回表优化

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

场景3:分页查询

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

InnoDB聚集索引普通索引,回表,索引覆盖

mysql 回表查询优化_MySQL优化:如何避免回表查询?什么是索引覆盖?相关推荐

  1. mysql 大分页查询优化_Mysql骚操作:优化大分页查询

    背景 系统结构如上图.经过排查是因为系统B拉取数据时间太长导致的推送超时. 系统B拉取数据的方法是根据_tiemstamp(数据操作时间)分页查询系统A的接口,即: 1SELECT 字段名2FROM  ...

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

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

  3. mysql优化表空间_MySQL 优化笔记

    记录学习笔记,持续更新. 优化方向 SQL优化 sql优化分析 索引优化 优化数据库对象 优化表的数据类型 表拆分(水平.垂直) 反范式 使用中间表 优化 mysql server mysql内存管理 ...

  4. mysql分页查询关键_MySQL优化教程之超大分页查询

    背景 基本上只要是做后台开发,都会接触到分页这个需求或者功能吧.基本上大家都是会用MySQL的LIMIT来处理,而且我现在负责的项目也是这样写的.但是一旦数据量起来了,其实LIMIT的效率会极其的低, ...

  5. mysql执行计划重用_MySQL 优化之EXPLAN执行计划

    MySQL优化之EXPLAN执行计划 ** 备注 ** 本文改编自https://www.processon.com/view/5d4fe8f4e4b04399f5a0303e?fromnew=1#m ...

  6. mysql自带查询优化_MySQL之select in 子查询优化的实现

    下面的演示基于MySQL5.7.27版本 一.关于MySQL子查询的优化策略介绍: 子查询优化策略 对于不同类型的子查询,优化器会选择不同的策略. 1. 对于 IN.=ANY 子查询,优化器有如下策略 ...

  7. mysql 横向分表合并_MySQL横向扩展-分库分表解决方案总结

    从业务场景看分库分表 互联网行业中,业务场景通常写少读多的情况居多,在MySQL的使用前期,读性能大多可以通过SQL优化来解决,但随着业务的持续发展,单纯依靠SQL的查询优化会越来越难以达到业务服务要 ...

  8. mysql如何备份一个表单_Mysql亿级数据大表单表备份

    上一篇Mysql已有亿级数据大表按时间分区,介绍了亿级数据大表如何按时间分区,也留下了一个问题:备份亿级数据大表要耗时多久.本篇将就如何备份亿级数据大表展开讨论. 注意:我这里所说的备份指的是数据从一 ...

  9. mysql 插入当前时间_MySql优化之前期探索

    一个系统中数据库往往会成为性能瓶颈,在开发阶段更多考虑的可能是功能的完成,随着系统的投入使用,数据量越来越大,sql语句查询速度慢的问题就会被凸显出来. 对于一个有sql语句性能为题的系统,如何找出问 ...

最新文章

  1. oracle xe 乱码_关于Linux操作系统下终端乱码的完美解决方法
  2. insert返回主键 — mybatis selectKey
  3. ssh key生成_Stelnet(ssh)登陆华为交换机配置教程
  4. 在Ubuntu|CentOS上安装Shutter截图工具及快捷键设置
  5. disk genius_如何预约Apple Store商店或Genius Bar
  6. c语言上机报告之水仙花数,C语言上机报告之水仙花数..doc
  7. UML类图与类间六种关系表示
  8. 计算机寄存器端口,CPU和外设之间的数据传送方式有哪几种
  9. OpenShift 4 - 为Serivce Account赋权
  10. 软件测试行业发展前景怎么样?
  11. 华硕java安装教程win10_华硕笔记本安装win10系统教程
  12. 解决MySQL workbench的Can‘t connect to MySQL server on ‘127.0.0.1‘(10061)问题
  13. matlab的libsvm工具箱(faruto版本)配置问题汇总,用于VS2015+R2017a
  14. WinForm程序启动控制台窗口Console
  15. android提交sql语句,Android实现创建或升级数据库时执行语句
  16. SQL注入:sqli-labs lesson-1 小白详解
  17. Python Day4 循环关键字和练习【零基础】
  18. java商城源码视频教程_Java商城秒杀系统设计视频教程学习下载(含项目源码)...
  19. 树莓派 环绕立体声卡 Audio Injector Octo 安装与测试
  20. 侃一侃萨班斯法案之302条款

热门文章

  1. javascript --- Object.assign()浅复制解决方法
  2. 如果您遇到文件或数据库问题,如何重置Joomla
  3. Zabbix 钉钉报警
  4. centos安装jenkins
  5. 大数据告诉你,电商都把假货发给谁?
  6. OSChina 周四乱弹 —— 熊孩子毁灭世界
  7. NoSQL系列:选择合适的数据库
  8. Directx11教程(55) 建立球形和锥形物体
  9. UNICODE编程资料(转贴)
  10. 消费类电子认证测试资料清单