通常大家都会根据查询的WHERE条件来创建合适的索引,不过这只是索引优化的一个方面。设计优秀的索引应该考虑到整个查询,而不单单是WHERE条件部分。索引确实是一种查找数据的高效方式,但是MySQL也可以使用索引来直接获取列的数据,这样就不再需要读取数据行。如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回到表中查询呢?如果一个索引覆盖所有需要查询的字段的值,我们就称之为“覆盖索引”。

覆盖索引是非常有用的工具,能够极大地提高性能:

索引条目通常远小于数据行大小,所以如果只需要读取索引,那MySQL就会极大地减少数据访问量。这对缓存的负载非常重要,因为这种情况下响应时间大部分花费在数据拷贝上。覆盖索引对于I/O密集型的应用也有帮助,因为索引比数据更小,更容易全部放入内存中。

因为索引是按照列值顺序存储的,所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少的多。对于某些存储引擎,例如MyISAM甚至可以通过OPTIMIZE命令使得索引完全顺序排列,这让简单的范围查询能使用完全顺序的索引访问。

一些存储引擎,如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据需要一次系统调用。这可能会导致严重的性能问题,尤其是那些系统调用找了数据访问中的最大的开销的场景。

由于InnoDB的聚簇索引,覆盖索引对InnoDB表特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。

在所有这些场景中,在索引中满足查询的成本一般比查询行要小得多。

不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引列的值,而哈希索引、空间索引和全文索引都不存储索引列的值,所以MySQL只能使用B+Tree索引所覆盖索引。另外,不同的存储引擎实现覆盖索引的方式也不同,而且不是所有的引擎都支持覆盖索引。

当发起一个呗索引覆盖的查询是,在EXPLAIN的Extra列可以看到“Using index”的信息。

如:explain select col1 from layout_test where col2=99

索引覆盖查询还有很多陷阱可能会导致无法实现优化。MySQL查询优化器会在执行查询前判断是否有一个索引能进行覆盖。假设索引覆盖了wehre条件中的字段,但不是整个查询涉及的字段。mysql5.5和更早的版本也总是会回表获取数据行,尽管并不需要这一行且最终会被过滤掉。

如:EXPLAIN select * from people where last_name='Allen' and first_name like '%Kim%'

image.png

这里索引无法覆盖该查询,有两个原因:

没有任何索引能够覆盖这个查询。因为查询从表中选择了所有的列,而没有任何索引覆盖了所有的列。不过理论上mysql有一个捷径可以利用:where条件中的列是由索引可以覆盖的,因此Mysql可以使用该索引找到对应的last_name并检查是否first_name是否匹配,过滤之后再读取所需要的数据行。

MySQL不能在索引中执行like操作。这是底层存储引擎API的限制。MySQL5.5和更早的版本只允许在索引中做简单的比较操作(等于、不等于及大于)。MySQL能在索引中做最左前缀匹配的LIKE比较,因为该操作可以转换为简单的比较操作,但是如果是通配符开头的LIKE查询,存储引擎无法做比较匹配。这种情况下,MySQL服务器只能提取数据行的值而不是索引值来做比较。

1. 如:EXPLAIN select * from people where last_name='Allen' and first_name like 'Kim%'

这条语句只检索1行,而之前的 like '%Kim%'要检索3行。

也有办法解决上面所说的两个问题,需要重写查询并巧妙设计索引。

EXPLAIN select * from people JOIN

( select id as childid from people where last_name='Allen' and first_name like '%Kim%' ) as t1 on (t1.childid=people.id)

这种方式叫做延迟关联,因为延迟了对列的访问。在查询第一个阶段MySQL可以使用覆盖索引,因为索引包含了主键id的值,不需要做二次查找。

-- 子查询利用到了覆盖索引

EXPLAIN select id from people where last_name='Allen' and first_name like '%Kim%'

在FROM子句的子查询中找到匹配的id,然后根据这些id值在外层查询匹配获取需要的所有列值。虽然无法使用索引覆盖整个查询,但总算比完全无法利用索引覆盖的好吧。

数据量大了怎么办?

这样优化的效果取决于WHERE条件匹配返回的行数。假设这个people表有100万行,我们看一下上面两个查询在三个不同的数据集上的表现,每个数据集都包含100万行。

第一个数据集。last_name为 ‘ming’ 的记录有30000条,其中对应的first_name包含 ‘xiao’ 的记录有20000条。

第二个数据集。last_name为 ‘ming’ 的记录有30000条,其中对应的first_name包含 ‘xiao’ 的记录有40条。

第三个数据集。last_name为 ‘ming’ 的记录有50条,其中对应的first_name包含 ‘xiao’ 的记录有10条。

实例1中,查询返回了一个很大的结果集,因此看不到优化的效果。大部分时间都花在读取和发送数据上了。

实例2中,经过索引过滤,尤其是第二个条件过滤后只返回了很少的结果集,优化的效果非常明显:在这个数据及上性能提高了很多,优化后的查询效率主要得益于只需读取40行完整数据行,而不是原查询中需要的30000行。

实例3中,子查询效率反而下降。因为索引过滤时符合第一个条件的结果集已经很小了,所以子查询带来的成本反而比从表中直接提取完整行更高。

在大多数存储引擎中,覆盖索引只能覆盖那些只访问索引中部分列的查询。不过,可以更进一步优化InnoDB。回想一下,InnoDB的二级索引的叶子节点都包含了主键的值,这意味着InnoDB的二级索引可以有效地利用这些额外的主键列来覆盖查询。

例如,people表中last_name字段有一个二级索引,虽然该索引的列不包括主键id,但也能够用于对id做覆盖查询:

select id,last_name from people where last_name='hua'

mysql的覆盖索引原理_「Mysql索引原理(七)」覆盖索引相关推荐

  1. 三极管工作原理_「硬见小百科」半导体三极管的工作原理

    PNP型半导体三极管和NPN型半导体三极管的基本工作原理完全一样,下面以NPN型半导体三极管为例来说明其内部的电流传输过程,进而介绍它的工作原理.半导体三极管常用的连接电路如图15-3(a)所示.半导 ...

  2. 深入浅出学习透析Nginx服务器的架构分析及原理分析「底层技术原理+运作架构机制」

    Nginx再次回顾 也许你已经忘记了Nginx是做什么的?我来再次给你夯实一下概念. 多协议反向代理 Nginx是个高性能的Web和反向代理服务器及HTTP服务器,它能反向代理HTTP,HTTPS和邮 ...

  3. mysql使用索引扫描做排序_「Mysql索引原理(八)」使用索引扫描做排序

    MySQL有两种方式可以生成有序的结果:通过排序操作:或者按索引顺序扫描:如果explain出来的type列的值为index,则说明MySQL使用了索引扫描来做排序. 扫描索引本身是很快的,因为只需要 ...

  4. mysql 按时间累计计算_精通MySQL索引背后的数据结构及算法原理

    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,mysql支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree ...

  5. mysql distinct多个字段_深入浅出Mysql索引的那些事儿

    一.索引的作用 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 在数据 ...

  6. mysql索引失效_导致MySQL索引失效的几种常见写法

    最近一直忙着处理原来老项目遗留的一些SQL优化问题,由于当初表的设计以及字段设计的问题,随着业务的增长,出现了大量的慢SQL,导致MySQL的CPU资源飙升,基于此,给大家简单分享下这些比较使用的易于 ...

  7. mysql优化原理_【MySQL】我必须得告诉你们的MySQL优化原理3(下)INNODB配置

    INNODB:使用最广的存储引擎 innodb-buffer-pool-size 若是大部分是InnoDB表,那么InnoDB缓冲池或许比其余任何东西都更须要内存,InnoDB缓冲池缓冲的数据:索引. ...

  8. mysql聚合索引创建_为 MySQL 查询优化选择最佳索引

    我们的许多用户.开发者和数据库管理员不断向我们的团队咨询有关 EverSQL 的索引推荐算法.所以,我们决定写一些这方面的内容. 本教程不会详细介绍该算法的所有内部特性,而是要简单地说明索引最重要的方 ...

  9. mysql group 索引失效_介绍mysql索引失效的情况

    mysql视频教程栏目索引失效的情况. 索引对于MySQL而言,是非常重要的篇章.索引知识点也巨多,要想掌握透彻,需要逐个知识点一一击破,今天来先来聊聊哪些情况下会导致索引失效. 图片总结版 相关免费 ...

最新文章

  1. 故障集合:那些年学习Linux坑你的故障集合
  2. NYOJ 84 阶乘的0
  3. 基础知识回顾——异常处理
  4. linux dhcp服务软包,dpkg包管理器详解
  5. uart怎么判断帧错误_UART通讯总线工作原理的理解--龚玉山
  6. 第五天 常用基本函数
  7. linux查看php命令目录权限,PHP执行linux命令mkdir权限问题
  8. 插件 KSImageNamed 用图片时自动显示图片缩略图
  9. python下载bt文件_python获取bt种子的详细信息
  10. android 常用adb 及linux 命令
  11. 自然场景文本检测识别技术集合(转)
  12. 基于MFC和OpenCV的摄像机定标与立体匹配测试程序
  13. linux低级格式化工具下载,Hard Disk Low Level Format Tool下载-硬盘低级格式化工具 v2.37 官方版 - 下载吧...
  14. Tomcat7下载与安装及eclipse中配置tomcat
  15. 邮件服务器 文件服务器,搭建邮件、终端和文件服务器应用方案
  16. 用命令行建立空白的simulink模型(mdl文件)(Matlab)
  17. SQL-92标准 中文翻译
  18. java实现IP归属地查询
  19. 一文读懂:DNA甲基化的作用及各种高通量检测方法比较
  20. 台式计算机把光驱改成硬盘,笔记本电脑光驱怎么改成硬盘|笔记本光驱位换成硬盘方法...

热门文章

  1. 算法设计与分析男女匹配问题C语言,C语言解决新郎和新娘配对问题代码解析
  2. 自学java的注意,自学Java开发注意事项
  3. 杰奇为什么只能用php5.2,杰奇2.2修改系统定义后,网站报错问题解决
  4. mysql数据库游标有什么特性_MySQL数据库游标的概念介绍和游标的使用讲解
  5. html 怎么让tr的css覆盖td的_html表格标签
  6. Karma和Jasmine自动化单元测试——本质上还是在要开一个浏览器来做测试
  7. sphinx索引文件进一步说明——最好是结合lucene一起看,直觉告诉我二者本质无异...
  8. python3 gzip 压缩/解压
  9. [bzoj1061] [NOI2008]志愿者招募
  10. C语言第一次实验报告