mysql中的回表查询与索引覆盖
了解一下MySQL中的回表查询与索引覆盖。
回表查询
要说回表查询,先要从InnoDB的索引实现说起。InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Secondary Index)。
InnoDB的聚集索引
InnoDB聚集索引的叶子节点存储行记录,因此InnoDB必须要有且只有一个聚集索引。
1.如果表定义了PK(Primary Key,主键),那么PK就是聚集索引。
2.如果表没有定义PK,则第一个NOT NULL UNIQUE的列就是聚集索引。
3.否则InnoDB会另外创建一个隐藏的ROWID作为聚集索引。
这种机制使得基于PK的查询速度非常快,因为直接定位的行记录。
InnoDB的普通索引
InnoDB普通索引的叶子节点存储主键值(MyISAM则是存储的行记录头指针)。
什么是回表查询
假设有个t表(id PK, name KEY, sex, flag),这里的id是聚集索引,name则是普通索引。
表中有四条记录:
| id | name | sex | flag |
| 1 | sj | m | A |
| 3 | zs | m | A |
| 5 | ls | m | A |
| 9 | ww | f | B |
聚集索引的B+树索引(id是PK,叶子节点存储行记录):

普通索引的B+树索引(name是KEY,叶子节点存储PK值,即id):

普通索引因为无法直接定位行记录,其查询过程在通常情况下是需要扫描两遍索引树的。
select * from t where name = 'lisi';
这里的执行过程是这样的:

粉红色的路径需要扫描两遍索引树,第一遍先通过普通索引定位到主键值id=5,然后第二遍再通过聚集索引定位到具体行记录。这就是所谓的回表查询,即先定位主键值,再根据主键值定位行记录,性能相对于只扫描一遍聚集索引树的性能要低一些。
索引覆盖
索引覆盖是一种避免回表查询的优化策略。具体的做法就是将要查询的数据作为索引列建立普通索引(可以是单列索引,也可以一个索引语句定义所有要查询的列,即联合索引),这样的话就可以直接返回索引中的的数据,不需要再通过聚集索引去定位行记录,避免了回表的情况发生。
覆盖索引的定义与注意事项
如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。
要注意的是,不是所有类型的索引都可以成为覆盖索引的。因为覆盖索引必须要存储索引的列值,而哈希索引、空间索引和全文索引等都不存储索引列值,索引MySQL只能使用B-Tree索引做覆盖索引。
另外,当发起一个被索引覆盖的查询(索引覆盖查询)时,在explain(执行计划)的Extra列可以看到【Using Index】的信息。
覆盖索引的优点
1.索引条目通常远小于数据行的大小,因为覆盖索引只需要读取索引,极大地减少了数据的访问量。
2.索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多。
3.一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点。
4.由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询。
"时刻保持谦虚,高情商是软实力。"
mysql中的回表查询与索引覆盖的更多相关文章
- MySQL中的全表扫描和索引树扫描
引言 在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况.在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type属性,ty ...
- mysql中如何删除表上的索引?删除索引?
需求描述: 今天在做SQL的优化的时候,想要把mysql中某个表上的索引删除掉,突然忘记语法了,找到帮助,在此记录下 操作过程: 1.查看表上的索引 show index from ti_o_sms; ...
- MySQL中的联表查询与子查询
0.准备数据 1.内连接:INNER JOIN 2.左连接:LEFT JOIN 3.右连接:RIGHT JOIN 4.USING子句 扩展知识点: 0.表别名的使用: 1.group by的用法 2. ...
- 数据库相关--mysql中的单表查询
一.完整的单表查询语句 select [distinct] *|字段1,字段2, .... from 表名 [where 条件1] [group by 字段名 [having 条件2] ] [orde ...
- mysql中的多表查询
基本模式:t1 CROSS JOIN t2, t1 INNER JOIN T2 ON ,以及LEFTJOIN 和RIGHT JOIN. 这些都需要在实践中使用,多练习才行. 写一句sql语句:SELE ...
- MySQL优化:如何避免回表查询?什么是索引覆盖? (转)
数据库表结构: create table user ( id int primary key, name varchar(20), sex varchar(5), index(name) )engin ...
- (MYSQL)回表查询原理,利用联合索引实现索引覆盖
一.什么是回表查询? 这先要从InnoDB的索引实现说起,InnoDB有两大类索引: 聚集索引(clustered index) 普通索引(secondary index) InnoDB聚集索引和普通 ...
- MySQL 回表查询 & 索引覆盖优化
回表查询 先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据 建表示例 mysql> create table user( -> id int(10) auto_incre ...
- MySQL回表查询
一.MySQL索引类型 1.普通索引:最基本的索引,没有任何限制 2.唯一索引(unique index):索引列的值必须唯一,但是允许为空 3.主键索引:特殊的唯一索引,但是不允许为空,一般在建表的 ...
随机推荐
- Lucene queryParser和analysis有什么不同?
在Lucene1.4.3中,queryParser和analysis分成独立的两个包,queryParser作用是解析查询语句,analysis作用是分词,queryParser在解析查询语句的时候会 ...
- jQuery 的58种事件方法你都用过了吗
jQuery 事件方法 事件方法触发或将函数附加到所选元素的事件处理程序. 下表列出了用于处理事件的所有jQuery方法. 方法 描述 bind() 在3.0版中已弃用. 请改用on()方法.将事件处 ...
- 在使用 Fortify进行源码扫描时需要做对项目需要做什么?
1.一般我们的项目都是svn 或git 进行管理的,为了扫出异常的问题 做好把 “” .svn “” 文件删除 2.把我们的项目需要的jar 文件放到一个文件夹内同项目一起进行扫描.这样为 ...
- jmeter5.1分布式压测
在使用jmeter压测过程中,可能会度遇到内存溢出的错误,这是为什么呢?因为jmeter是java写的应用,java应用jvm堆内存heap受负载机硬件限制,虽然我们可以调整堆内存大小,但是单机无法支 ...
- 关与 @EnableConfigurationProperties 注解
@EnableConfigurationProperties注解的作用是: 让使用 @ConfigurationProperties 注解的类生效. 当@EnableConfigurationProp ...
- 【IDE_IntelliJ IDEA】idea中设置类和方法的注释模板
参考博文:idea生成类注释和方法注释的正确方法
- Linux(Centos7)搭建LAMP(Apache+PHP+Mysql环境)
目录 Linux搭建LAMP(Apache+PHP+Mysql环境)Centos7 一. 检查系统环境 1.确认centos版本 2.检查是否安装过apache 3.检查是否安装过Mysql 4.清理 ...
- Ubuntu18.04.2安装中文输入法
转载请注明出处: BooTurbo https://www.cnblogs.com/booturbo/p/11287557.html 1.英文的Ubuntu系统,首先要安装中文语言,在 Settin ...
- 快速、优雅的前端IDE之H-builder-X
为什么介绍的是HBuidler-X而不是Hbuilder HX是全新的一个软件,它抛弃了eclipse架构,使用C++为基础架构.HX目前还不能完全替代HBuilder.但在markdown记事的 ...
- 201871010112-梁丽珍《面向对象程序设计(java)》第十五周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...