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

覆盖索引是非常有用的工具,能够极大的提高性能。考虑一下如果查询只需要索引而无需返回表,会带来多大好处:

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

因为索引是按照列值顺序存储的(至少在单个页内是如此),所以对于IO密集型的范围查询会比随机从磁盘读取没以后数据的io要小的多。对于某些存储引擎,例如MyISAM,甚至可以通过OPTIMIZE命令使得索引完全顺序排列,这让简单的范围查询能使用完全顺序的索引访问。

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

由于InnoDB的聚簇索引,覆盖索引对InnoDB表特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。在所有这些场景中,索引中满足查询的成本一般比查询要小的多。

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

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

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

有如下查询:

SELECT * FROM produs WHERE actor="Bob" AND title LIKE"%A%"

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

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

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

也有办法解决上面所说的两个问题,需要重写查询并巧妙的设计索引。先将索引扩展至覆盖三个数据列(artist,title,prod_id)然后按照如下的方式重写查询。

SELECT * FROM products JOIN(SELECT prod_id from products WHERE actor="BOB" and title like "%A%") AS t1 on (t1.pro_id = products.prod_id) .

我们把这种方式叫做延迟关联(deferred join),因为延迟了对列的访问。在查询的第一阶段MySQL可以使用覆盖索引,在FROM 子句的子查询中找到匹配的prod_id,然后根据这prod_id值在外出查询匹配获取需要的所有列值。虽然无法使用索引覆盖整个查询,但总比完全无法利用索引覆盖的好。

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

第一个数据集:Bob 出演了3W部作品,其中有2W部标题中包含A

第二个数据集:Bob..........3W.......,............40部..........

第三个数据集:...............50部。。。。。。。。10部。。。。

数据集    原查询    优化后查询

1      每秒5次    每秒5次

2      每秒7次    每秒35次

3      每秒2400次  每秒2000次

下面是对结果的分析:

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

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

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

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

mysql 覆盖索引_MySQL 覆盖索引相关推荐

  1. mysql高效索引覆盖索引_MySQL高效索引:覆盖索引

    原标题:MySQL高效索引:覆盖索引 作者:踏雪无痕 cnblogs.com/chenpingzhao/p/4776981.html 概念 如果索引包含所有满足查询需要的数据,则该索引称为覆盖索引(C ...

  2. mysql 创建覆盖索引_MySql覆盖索引

    mysql的innodb引擎通过搜索树方式实现索引,索引类型分为主键索引和二级索引(非主键索引),主键索引树中,叶子结点保存着主键即对应行的全部数据:而二级索引树中,叶子结点保存着索引值和主键值,当使 ...

  3. mysql 创建覆盖索引_Mysql覆盖索引 covering index 或者 index coverage

    组合索引 提到组合索引,大家都知道"最左前缀"原则.例如,创建索引 idx_name_age (name,age) ,通常情况下,where age=50 或者 where age ...

  4. mysql innerdb 索引_mysql innodb索引原理

    聚集索引(clustered index) innodb存储引擎表是索引组织表,表中数据按照主键顺序存放.其聚集索引就是按照每张表的主键顺序构造一颗B+树,其叶子结点中存放的就是整张表的行记录数据,这 ...

  5. mysql的联合索引_mysql联合索引

    联合索引 概念 联合索引又叫复合索引,即一个覆盖表中两列或者以上的索引,例如: index_name(column a,column b) 1 创建方式 执行alter table语句时创建 alte ...

  6. mysql 索引_MySQL之索引

    索引查找算法BTREE BTREE查找算法演变B-TREE :普通 BTREE,平衡多路查找树(B-Tree)B+TREE :叶子节点双向指针B++TREE(B*TREE):枝节点的双向指针 普通B- ...

  7. mysql 堆表_Mysql聚集索引和非聚集索引(堆组织表和索引组织表)

    Mysql聚集索引和非聚集索引(堆组织表和索引组织表) 1.堆组织表(HOT)和索引组织表(IOT)有什么区别? myisam使用的堆组织表(Heap Organize Table, HOT),没有聚 ...

  8. mysql为什么要重建索引_MySQL表索引为什么会遭破坏?

    此文章主要向大家描述的是MySQL表索引被破坏的问题的产生缘由,以及针对这一问题我们给出其具体的解决方案,下面的文章就是对其相关内容的具体介绍,希望在你今后的学习中会有所帮助. 下午上班,惊闻我的de ...

  9. mysql 破坏索引_mysql表索引被破坏的问题及解决

    用mysql的用户,经常会遇到这样的问题,检查mysql日志,错误信息为: Table '.\dedecmsv4\dede_archives' is marked as crashed and sho ...

  10. java中mysql数据库原理_MySql数据库索引原理

    本文主要是阐述索引机制,主要是说明存储引擎Innodb 第一部分主要从及理论层面讨论MySQL索引的数理基础. 第二部分结合MySQL数据库中InnoDB数据存储引擎中索引的实现讨论聚集索引.非聚集索 ...

最新文章

  1. Linux的账号口令机制及其爆破
  2. hdu1042 java_N! hdu1042 | 学步园
  3. python3.7界面设计_基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架
  4. 万字长文 - 解读功能开关 | IDCF
  5. LeetCode 1186. 删除一次得到子数组最大和(DP)
  6. 二叉树经典题之将二叉树分层打印
  7. python能以文本和二进制方式处理文件_使用Python进行二进制文件读写的简单方法(推荐)...
  8. 删除Github上项目
  9. 事业单位计算机岗位考公基吗,江苏事业单位统考考公基吗
  10. python 解析模块脚本_Python HTMLParser模块解析html获取url实例
  11. 蓝桥杯官网 试题 PREV-94 历届真题 矩阵计数【第十届】【决赛】【研究生组】【C++】解法
  12. 可编程接口芯片8255A
  13. IDEA 默认浏览器修改设置
  14. winedt103系统找不到指定文件_latex排版(CTeX winEdit输出“系统找不到指定的文件”的终极解决办法)...
  15. 猫、路由器、带宽、IP地址、子网掩码、网关以及公网与私网简介
  16. 朱松纯教授:可解释性是人工智能获得人类信任的关键
  17. 全球与中国消防系统市场现状及未来发展趋势
  18. 数据分析师之所需要了解的产品系列知识(二)——如何测试产品健康
  19. 《动手学深度学习》学习之路01-- Kaggle⽐赛:房价预测
  20. Html5笔记之第一天

热门文章

  1. 王乐园 php_见到海贼王主题乐园的雕像,感觉认知回不去了,索隆是认真的?...
  2. BZOJ3091 城市旅行
  3. LVM 逻辑卷管理(实战篇)
  4. pwd 打印当前所在目录
  5. python执行命令不阻塞_通过python 执行 nohup 不生效的解决
  6. java程序员选择多个offer时需要看重哪些?_27 道阿里巴巴 Java 面试题,你会几道?...
  7. 参数等效模型可以用于_扬声器单元的等效电路分析与应用(1)
  8. python程序基本结构有哪三种_【Python基础】Python程序结构有哪些
  9. 城市轨道交通运营管理属于什么院系_青西新区高职校城市轨道交通运营与管理专业礼仪教学成果考核圆满结束...
  10. 百度测试linux面试题,【百度百度Linux面试题】面试问题:Linux查看… - 看准网