MySQL 覆盖索引
通常大家都会根据查询的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覆盖索引与延迟关联
延迟关联:通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据. 为什innodb的索引叶子节点存的是主键,而不是像myisam一样存数据的物理地址指针? 如果存的是物理地址指针不 ...
- mysql覆盖索引与回表
mysql覆盖索引与回表 Harri2012关注 62019.07.28 11:14:15字数 1,292阅读 77,322 select id,name where name='shenjian' ...
- mysql覆盖索引详解
覆盖索引的定义: 如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’.即只需扫描索引而无须回表. 只扫描索引而无需回表的优点: 1.索引条目通常远小于数据行大小,只需要读取索引, ...
- mysql覆盖索引(屌的狠,提高速度)
话说有这么一个表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NULL, ...
- mysql覆盖索引
话说有这么一个表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NU ...
- Mysql覆盖索引 covering index 或者 index coverage
组合索引 提到组合索引,大家都知道"最左前缀"原则.例如,创建索引 idx_name_age (name,age) ,通常情况下,where age=50 或者 where age ...
- mysql延迟查询, 覆盖索引使用例子
引用自 'mysql高性能' 5.3.6章节 不能使用覆盖索引的情况 : 解决办法 :
- 理解MySQL数据库覆盖索引
话说有这么一个表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NULL, ...
- MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析
文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...
随机推荐
- mysql时间int日期转换
select from_unixtime(1350437720);select unix_timestamp(now());插入用 unix_timestamp(date)查询用from_unixti ...
- 【结构型】Adapter模式
Adapter模式主要意图是将类或接口转换成客户期望的接口,从而使得原本不兼容.无法在一起工作的接口可以在一起工作.该模式有两种形式的Adapter法,一是继承方式:二是对象关联依赖方式. 继承方式A ...
- 关于tcc、tlink的编译链接机制的研究
1.学习过程 在c:\下建立文件夹c,并将编译器tcc.exe.连接器tlink.exe.相关文件c0s.obj.cs.lib.emu.lib.maths.lib放入文件夹中. 要搭建一个简单的C语言 ...
- mobile javascript
http://www.cnblogs.com/zhepama/archive/2013/06/01/3112023.html http://www.csdn.net/article/2014-01-0 ...
- Drag & Drop and File Reader
参考 : http://www.html5rocks.com/zh/tutorials/file/dndfiles/ http://blog.csdn.net/rnzuozuo/article/det ...
- Stack的三种含义(数据超过栈的大小,就发生stack overflow)
非常典型的基础知识,转自http://www.ruanyifeng.com/blog/2013/11/stack.html 学习编程的时候,经常会看到stack这个词,它的中文名字叫做"栈& ...
- COJ 0020 30201象棋中的皇后
30201象棋中的皇后 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 在n×m的棋盘上放置两个相互攻击的皇后,总共有多少种不同 ...
- HDU_2024——判断字符串是否是c语言合法标识符
Problem Description 输入一个字符串,判断其是否是C的合法标识符. Input 输入数据包含多个测试实例,数据的第一行是一个整数n,表示测试实例的个数,然后是n行输入数据,每行是 ...
- 素数与素性测试(Miller-Rabin测试)
转载自Matrix大牛的博客 把代码翻译成C++ http://www.matrix67.com/blog/archives/234 题目链接: http://hihocoder.com/proble ...
- IT项目外包有哪些注意事项
2015年两会上,李克强总理在政府工作报告中首次提出“互联网+”计划,各种互联网创业项目也如雨后春笋般破土而出.由于很多创业团队并没有自己的技术团队,所以软件外包成为很多创业项目普遍采取的一种方案.在 ...