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

转自: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

4e64649658b472652588de7eef87ca3a.png

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

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

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

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

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

例如:

是如何执行的呢?

3119450ce7cc31a54b418b1c6acede66.png

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

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

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

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

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

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

画外音:治学严谨吧?

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

da2caa733c9d26cdcd42b30002d245e3.png

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

a62bf703a7c0dc4582236a33f57a0e11.png

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

三、如何实现索引覆盖?

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

仍是之前中的例子:

第一个SQL语句:

0c6eb8b1f89a2da24c82a73e4aec5eec.png

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

画外音,Extra:Using index。

第二个SQL语句:

cb2e6ad6be14e20465e6d84e09966d0b.png

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

画外音,Extra:Using index condition。

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

059f6219b3fc301a4f7fba07e9537f1f.png

可以看到:

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

画外音,Extra:Using index。

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

场景1:全表count查询优化

582a0e64783a955462154b5f9817c532.png

原表为:

user(PK id, name, sex);

直接:

不能利用索引覆盖。

添加索引:

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

场景2:列查询回表优化

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

场景3:分页查询

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装 Windows 自动化 API 3.0 后,Visual Studio 2010 的运行速度更快

安装 Windows 自动化 API 3.0 后,Visual Studio 2010 的运行速度更快 本文适用于以下产品: Microsoft Visual Studio 2010如果未安装 Windows 自动化 API 3.0,则使用 Windows 自动化 API 的应用程序会明显降低 Microsoft Visual Studio Inte…

cocos2d-x3.2创建项目

mac: 1.用终端进入/Users/lixiang/Desktop/cocos2d-x-3.2/tools/cocos2d-console/bin目录执行./cocos.py。 (出现Permission denied,是权限问题,可以先使用chmod命令获得权限,输入chmod ux ./cocos.py 回车&#xff0c…

使用ASP.Net WebAPI构建REST服务(一)——简单的示例

由于给予REST的Web服务非常简单易用,它越来越成为企业后端服务集成的首选方法。本文这里介绍一下如何通过微软的Asp.Net WebAPI快速构建REST-ful 服务。 首先创建一个Asp.Net Web应用程序(我这里用的是Visual Studio 2013,它已经内置了Web AP…

网页游戏服务器配置

最近要架设一个网页游戏,就到硬件市场配了一台服务器,下面是具体的配置清单: Intel Xeon 5310 1.6G 1350  金士顿4GB DDR2 667(ECC FB DIMM)*2 全缓冲处理内存 680*2  主板 Intel S5000VSA 1750  硬盘 320G SATA*2 450*2   国鑫GX514…

Linux sudo命令详解

Linux sudo命令以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。 使用权限:在 /etc/sudoers 中有出现的使用者。 简单的说,sudo 是一种权限管理机制,管理员可以授权于一些普通用户…

告别花瓶:2015年智能电视路在何方?

智能手机与平板在IT市场风生水起,让几岁小孩到大爷大妈们都对玩手机、平板乐此不彼。曾经辉煌几十年的电视行业,如今又重新融合了智能系统以全新的面貌出现在人们面前。多家互联网企业对这一“翻新”的市场虎视眈眈,并推出了多款智能电视。但…

文件类型

转载于:https://www.cnblogs.com/hlc-123/p/10958326.html

灾备还缺一套评价体系

1月10日,灾备技术产业联盟正式成立。这样一个中立的、由业内众多厂商和大型用户组成的、以服务为宗旨的联盟将为我国灾备技术和应用的规范化发展做出积极贡献。经过一年多的酝酿、历经7次筹备会议,由华为、北京邮电大学、中治研国际信息技术研究院和中国…

DFS知识点

2019-06-01 11:14:34 加油,坚持!!! 1. 2. 3. 转载于:https://www.cnblogs.com/Artimis-fightting/p/10960409.html

Sery送的书与网站短信解决方案

今天Sery(http://sery.blog.51cto.com/)在qq上说要送我一本他刚写的书《互联网运营智慧》,因为里面引用了我写的一段程序。 #!/usr/bin/perl -w use strict; use LWP::Simple; use URI::Escape; use Digest::MD5; my ($mobile, $content) AR…

兰州财经大学JAVA期末考什么_兰州财经大学大学国文下答案

兰州财经大学大学国文下答案更多相关问题建立HSE管理体系可提高企业安全、环境和健康()。A.管理水平B.操作水平C.使用水平D.能源水平计算机保存矢量图形实际上是存储描述矢量图形的一组绘图指令及有关的参数,因此 矢量图形的存储取样频率、量化精度将影响录制数字音…

Android 反射获取内外置存储卡方法

2019独角兽企业重金招聘Python工程师标准>>> 以前的Android(4.1之前的版本)中,SDcard跟路径通过“/sdcard”或者“/mnt/sdcard”来表示存储卡,而在Jelly Bean系统中修改为了“/storage/sdcard0”,以后可能还会有多个SDcard的情况。…

docker安装mysql redis_Docker安装Mysql和Redis以及构建部署应用镜像

为了方便本地测试项目,为了方便开启新的环境,为了方便部署,打算本地利用Docker安装Mysql和Redis。搭建Springboot项目,编写Dockerfile,打包构建镜像。简单使用docker-compose启动服务。简述docker-compose和K8S。环境系…

plsql if

set serveroutput onaccept num prompt 请输入一个数字; declare pnum number : #beginif pnum0 then dbms_output.put_line(您输入的数据是0);elsif pnum1 then dbms_output.put_line(您输入的数据是1);elsif pnum2 then dbms_output.put_line(您输入的数据是2);e…

Windows 下查看端口占用情况 netstat / tasklist / findstr

为什么80%的码农都做不了架构师?>>> Windows服务器不熟悉很多,尤其是防火墙这块。不过其实和Linux一样,省事的话就是关了就好了。不过对于端口占用还是时常有的,比如QQ音乐,迅雷这些,如果你的电…

unicode 字符串转成 TDesC-转贴

unicode 字符串转成 TDesC所有描述符,其实都不是真实的类,而是一个typedef。在非内核模式的时候,所有的描述符,如TDesC,其真实的实现是TDesC16,在内核模式的时候,则是TDesC8。还是看名取义&…

第二阶段团队冲刺(七)

1、我昨天的成就:从老师那里要来了完整的无课表信息,不需要再从网站爬取,无课表导入数据库 2、遇到什么困难:无课表导入数据库格式兼容问题 3、今天的任务 :购买阿里云服务器并配置 转载于:https://www.cnblogs.com/Ad…

java任务poer_java-Powermock-模拟超级方法调用

这是我的代码-import org.junit.Test;import org.junit.runner.RunWith;import org.powermock.modules.junit4.PowerMockRunner;import org.powermock.core.classloader.annotations.*;import static org.powermock.api.support.SuppressCode.*;class BaseService {public int …

2015 年度计划

2019独角兽企业重金招聘Python工程师标准>>> scala -> akka -> sparketcd 使用开源产品 negroni https://github.com/codegangsta/negroni转载于:https://my.oschina.net/kuerant/blog/372981

Mybatis 动态传sql可以查询表名,任意表名,不固定字段的个数返回未定义的类型以及增删改...

mysql查询表名: SELECT table_name FROM information_schema.tables WHERE table_schemasell AND table_typebase table;查询表中的字段: SELECT column_name FROM information_schema.columns WHERE table_schemasell AND table_nameseller_infoSpringB…