mysql优化:覆盖索引(延迟关联)
前言
上周新系统改版上线,上线第二天就出现了较多的线上慢sql查询,紧接着dba 给出了定位及解决方案,这里较多的是使用延迟关联去优化。
而我对于这个延迟关联也是第一次听说(o(╥﹏╥)o),所以今天一定要学习并产出一篇学习笔记。(^▽^)
回表
我们都知道InnoDB采用的B+ tree来实现索引的,索引又分为主键索引(聚簇索引)和普通索引(二级索引)。
那么我们就来看下基于主键索引和普通索引的查询有什么区别?
- 如果语句是select * from T where ID=500,即主键查询方式,则只需要搜索ID这棵B+树;
- 如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次。这个过程称为回表。
举个栗子:

可以看出我们有一个普通索引k,那么两颗B+树的示意图如下:

(注:图来自极客时间专栏)
当我们查询 select * from T where k=5 其实会先到k那个索引树上查询k = 5,然后找到对应的id为500,最后回表到主键索引的索引树找返回所需数据。
如果我们查询select id from T where k=5 则不需要回表就直接返回。
也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。
覆盖索引
- 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
- 解释二: 索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫做覆盖索引。
- 解释三:是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。
- 不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引
- 当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息
概念如上,这里我们还是用例子来说明:

(注:图来自极客时间专栏)
现在,我们一起来看看这条SQL查询语句的执行流程: select * from T where k between 3 and 5
- 在k索引树上找到k=3的记录,取得 ID = 300;
- 再到ID索引树查到ID=300对应的R3;
- 在k索引树取下一个值k=5,取得ID=500;
- 再回到ID索引树查到ID=500对应的R4;
- 在k索引树取下一个值k=6,不满足条件,循环结束。
在这个过程中,回到主键索引树搜索的过程,我们称为回表。可以看到,这个查询过程读了k索引树的3条记录(步骤1、3和5),回表了两次(步骤2和4)。
在这个例子中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有可能经过索引优化,避免回表过程呢?
如果执行的语句是select ID from T where k between 3 and 5,这时只需要查ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
需要注意的是,在引擎内部使用覆盖索引在索引k上其实读了三个记录,R3~R5(对应的索引k上的记录项),但是对于MySQL的Server层来说,它就是找引擎拿到了两条记录,因此MySQL认为扫描行数是2。
延迟关联
上面介绍了那么多 其实是在为延迟关联做铺垫,这里直接续上我们本次慢查询的sql:


我们都知道在做分页时会用到Limit关键字去筛选所需数据,limit接受1个或者2个参数,接受两个参数时第一个参数表示偏移量,即从哪一行开始取数据,第二个参数表示要取的行数。 如果只有一个参数,相当于偏移量为0。
当偏移量很大时,如limit 100000,10 取第100001-100010条记录,mysql会取出100010条记录然后将前100000条记录丢弃,这无疑是一种巨大的性能浪费。
当有这种写法时,我们可以采用延迟关联来进行优化,重点关注:SELECT id FROM qa_question WHERE expert_id = 69 AND STATUS = 30 ORDER BY over_time DESC LIMIT 0, 10, 这里其实利用了索引覆盖,where条件后的expert_id 是有添加索引的,这里查询id 可以避免回表,大大提升效率。
结语
工作中会遇到各种各样的问题,对于一个研发来说最重要的是能够从这些问题中学到什么。好久没有写博客了,究其原因还是自己变得懒惰了。 ( ̄ェ ̄;)
最后以《高性能Mysql》中的一段话结束:


mysql优化:覆盖索引(延迟关联)的更多相关文章
- mysql分页查询优化(索引延迟关联)
对于web后台报表导出是一种常见的功能点,实际对应服务后端即数据库的排序分页查询.如下示例为公司商户积分报表导出其中一个sql ,当大批量的导出请求进入时候,mysql的cpu急剧上升瞬间有拖垮库的风 ...
- mysql优化-覆盖索引查询,join
1 原始sql: SELECT a.* FROM event_data a WHERE a.receive_time >= '2018-03-28 00:00:00' AND a.receive ...
- SQL Server查询性能优化——覆盖索引(二)
在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...
- mysql 优化之索引的使用
mysql 优化之索引的使用 1:MySQL 索引简介: MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL ...
- 【Mysql优化】索引优化策略
1:索引类型 1.1 B-tree索引 注: 名叫btree索引,大的方面看,都用的平衡树,但具体的实现上, 各引擎稍有不同, 比如,严格的说,NDB引擎,使用的是T-tree Myisam,in ...
- 理解MySQL数据库覆盖索引
话说有这么一个表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NULL, ...
- mysql优化之索引优化
Posted by Money Talks on 2012/02/23 | 第一篇 序章第二篇 连接优化第三篇 索引优化第四篇 查询优化第五篇 到实战中去 索引优化 索引优化涉及到几个方面,包括了索引 ...
- 理解MySQL数据库覆盖索引 (转)
http://www.cnblogs.com/zl0372/articles/mysql_32.html 话说有这么一个表: CREATE TABLE `user_group` ( `id` int( ...
- Mysql优化之索引
前言 这几天抽了个时间将<高性能Mysql>看了一下忽觉索引非常之重要,习之然后总结巩固知识.本文索引使用的是InnoDB存储引擎.因为本文并不是说用索引的好处,所以并不会书写QPS之类的 ...
- 第九课——MySQL优化之索引和执行计划
一.创建索引需要关注什么? 1.关注基数列唯一键的数量: 比如性别,该列只有男女之分,所以性别列基数是2: 2.关注选择性列唯一键与行数的比值,这个比值范围在0~1之前,值越小越好: 其实,选择性列唯 ...
随机推荐
- python_regex
正则表达动机(目的): 1.处理文本成为计算机主要工作之一 2.根据文本内容进行固定搜索是文本处理的常见工作 3.为了快速方便的处理上述问题,正则表达式技术诞生,逐渐发展为一种单独技 ...
- NSURLConnection发送GET请求
// ViewController.m // 04-掌握-NSURLConnection发送GET请求 // // Created by xiaomage on 16/2/22. // Copyrig ...
- Django2.2 Templates 页面渲染 数据列表跳转 以及简单的页面模块继承
声明:本博客用的为pycharm Django2.2,基于此内容,会简单讲解 数据库传参形式的增删查改(完整小项目) 路由的 位置参数.关键字参数.以及html中反向解析路由 request的表单传递 ...
- JQuery动态添加控件并取值
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- Spring Cloud(二):Eureka 服务注册中心
前言 服务治理 随着业务的发展,微服务应用也随之增加,这些服务的管理和治理会越来越难,并且集群规模.服务位置.服务命名都会发生变化,手动维护的方式极易发生错误或是命名冲突等问题.而服务治理正是为了解决 ...
- Javascript实现百度API
百度地图JavaScript API是一套由JavaScript语言编写的应用程序接口,可帮助您在网站中构建功能丰富.交互性强的地图应用,支持PC端和移动端基于浏览器的地图应用开发,且支持HTML5特 ...
- 机器学习笔记(六) ---- 支持向量机(SVM)【华为云技术分享】
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...
- sbt assembly a fat jar for spark-submit cluster model
在用spark-submit提交作业时,用sbt package打包好的jar程序,可以很好的运行在client模式,当在cluster模式, 一直报错:Exception in thread &qu ...
- 为什么查询出来的数据保存到Arraylist?插入删除数据为啥用LinkedList?
引言:这是我在回答集合体系时,被问到的一个问题,也是因为没有深入学习所以回答的并不是很好,所以这两天看了一下,以下是我的一些回答与学习方法. 学习方法:我们学习,系统性的学习肯定是比零散的学习更有效的 ...
- SpringBoot-多环境切换相关(六)
多环境切换 profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境: 方式一:多配置文件 我们在主配置文件编写的时候,文件名可以是 applicat ...
