通常大家都会根据查询的where条件来创建合适的索引,不过这只是索引优化的一个方面。索引确实是一种查找数据的高效方式,但是mysql也可以使用索引来直接获取列的数据,这样就不再需要读取数据行。如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢?如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为“覆盖索引”。
一、覆盖索引的优点
覆盖索引是非常有用的工具,能够极大的提高性能。如果查询只需要扫描索引而无需回表,会带来多少好处:
- 索引条目通常远小于数据行大小,所以如果只需读取索引,那mysql就会极大的减少数据访问量。这对缓存的负载非常重要,因为这种情况下响应时间大部分花费在数据拷贝上。覆盖索引对于I/O密集型的应用也很有帮助,因为索引比数据更小,更容易全部放入内存中。
- 因为索引是按照列值顺序存储的,所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少的多。对于某些存储引擎,例如MyISAM,甚至可以通过optimize命令使得索引完全顺序排列,这让简单的范围查询能使用完全顺序的索引访问。
- 一些存储引擎如MyISAM在内存中只缓存索引,数据则依赖于操作系统来缓存,因此要访问数据需要一次系统调用。这可能会导致严重的性能问题,尤其是那些系统调用占用了数据访问中的最大开销的场景。
- 由于InnoDB的聚簇索引,覆盖索引对InnoDB特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。
二、覆盖索引的适用范围
不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引列的值,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以mysql只能使用B-Tree索引做覆盖索引。另外,不同的存储引擎实现覆盖索引的方式也不同,而且不是所有的引擎都支持覆盖索引。
三、有关覆盖索引的优化问题
当发起一个被索引覆盖的查询时,在EXPLAIN的extra列可以看到“Using index”的信息。索引覆盖查询还有很多陷阱可能会导致无法实现优化。MySQL查询优化器会在执行查询前判断是否有一个索引能进行覆盖。假设索引覆盖了where条件中的字段,但不是整个查询涉及的字段。如果条件为假,MySQL5.5或更早的版本也总是会回表获取数据行,尽管并不需要这一行且最终会被过滤掉。
为什么会发生这样的情况,以及如何重写查询以解决该问题?这里索引无法覆盖该查询,有两个原因:
- 没有任何索引能够覆盖这个查询。因为查询从表中选择了所有的列,而没有任何索引覆盖了所有的列。不过,理论上MySQL还有一个捷径可以利用:where条件中的列是有索引可以覆盖的,因此MySQL可以使用该索引找到对应的索引列数据并检查索引列上列数据是否匹配,过滤之后再读取需要的数据行。
- MySQL不能在索引中执行like操作。这是底层存储引擎API的限制,MySQL5.5和更早的版本中只允许在索引中做简单比较操作(例如等于、不等于以及大于)。MySQL能在索引中做最左前缀匹配的like比较,因为该操作可以转换为简单的比较操作,但是如果是通配符开头的like查询,存储引擎就无法做比较匹配。这种情况下,MySQL服务器只能提取数据行的值而不是索引值来做比较。
其实也有办法解决上面所说的两个问题,需要重写查询并巧妙的设计索引。看下面的例子:
1、首先将索引扩展至覆盖三个数据列(actor、title、prod_id);
2、然后按照如下方式重写查询:select * from products join (select prod_id from products where actor='sean_carrey' and title like '%apollo%' ) as t1 on (t1.prod_id = products.prod_id);
这种方式叫做延迟关联,因为延迟了队列的访问。在查询的第一阶段MySQL可以使用覆盖索引,在from子句的子句中找到匹配的prod_id,然后根据这些prod_id值在外层查询匹配所需要的所有列值。虽然无法使用覆盖索引覆盖整个查询,但总算比完全无法利用覆盖索引的好。
在大多数存储引擎中,覆盖索引只能覆盖那些只访问索引中部分列的查询。不过,可以更进一步优化InnoDB。回想一下,InnoDB的二级索引的叶子节点包含了主键的值,这意味着InnoDB的二级索引可以有效的利用这些“额外”的主键列来覆盖查询。
相关推荐
MySQL覆盖索引是一种优化策略,它允许查询仅通过索引本身获取所需的所有数据,而无需回表查询实际的数据行。这种技术可以显著提高查询速度,因为它减少了数据访问量,特别是对于那些只涉及到索引列的查询。覆盖索引...
5. **覆盖索引**:当查询只需要索引中的数据时,使用覆盖索引可以避免回表操作,显著提高查询速度。 6. **定期分析和优化**:定期使用ANALYZE TABLE或OPTIMIZE TABLE来更新统计信息,确保MySQL能准确估计查询成本。 ...
2. **覆盖索引**:当查询只需要索引中的列时,使用覆盖索引可以避免回表,提高性能。 3. **避免全表扫描**:尽量让MySQL能够利用索引来定位数据,减少`type`列中`all`的出现。 4. **考虑查询语句的顺序**:优化器...
此外,了解并运用Oracle的索引优化特性也很重要,如索引组织表(Index-Organized Table, IOT)、覆盖索引(Covering Index)以及物化视图(Materialized View)等。 总的来说,Oracle索引详解及SQL优化是一个深度...
1. **创建覆盖索引**:确保索引包含所有查询所需的列,以避免额外的数据读取。 2. **使用最合适的索引类型**:根据查询条件选择最合适的数据类型,如使用 `BTREE` 或 `HASH` 索引。 3. **定期维护索引**:定期...
同时,合理使用覆盖索引(即查询列完全包含在索引中)可以提高查询速度。 总结,"Explain"是MySQL性能分析的重要工具,通过其输出我们可以了解查询执行的细节,找出性能瓶颈并进行优化。配合合理的索引设计,可以...
- 使用覆盖索引(covering index),即索引包含了所有查询需要的列,可以避免回表操作,提高查询速度。 - 考虑复合索引的顺序,通常将选择性更强的列放在前面。 - 避免在索引列上使用函数,因为这会阻止MySQL使用...
前言 之前在网上看到过很多关于mysql联合索引最左前缀匹配的文章,自以为就了解了其原理,最近面试时和面试官交流,发现遗漏...覆盖索引:假如查询SELECT col1, col2, col3 FROM 表名,由于查询的字段存在索引页中,那
### MySQL索引详解 #### 一、MySQL索引概述 索引在数据库中扮演着至关重要的角色,它能够显著提高数据检索的速度。简单来说,索引就像图书的目录一样,帮助用户快速定位所需数据的位置。当数据库表中的数据量增大...
压缩包中的"02"索引文件很可能包含更深入的索引知识,比如聚集索引与非聚集索引的区别、覆盖索引的概念、分区索引的用法、索引重建和优化策略等。这部分内容将帮助你进一步理解索引的复杂性和实际应用。 总的来说,...
此外,优化索引策略包括选择合适的数据类型,避免在索引列上使用函数,以及适时使用覆盖索引以减少全表扫描。 总之,Oracle索引通过B树结构提供快速的数据访问路径,但需要谨慎管理,以平衡查询性能和存储及维护...
4. 使用覆盖索引:查询时,如果索引包含所有需要的数据,MySQL可以直接从索引中获取结果,无需回表,提高效率。 5. 避免在索引列上使用函数:函数会阻止索引的直接使用。 五、索引维护 1. 定期分析索引:使用`...
10. Extra:包含其他信息,如“Using index”表示使用覆盖索引,“Using where”表示在索引中应用了WHERE条件。 理解这些参数可以帮助优化查询,例如,通过降低rows的值来减少扫描的行数,或者使用覆盖索引来避免回...
- **按覆盖字段分类**: 单列索引与组合索引。 - **单列索引**: 针对单个列创建的索引。 - **组合索引**: 包含两个或更多列的索引。 - **按数据结构分类**: B-Tree索引、哈希索引、R-Tree索引等。 - **B-Tree...
第四部分(LinuxC.pdf)可能是全书的概述或索引,方便读者快速查找所需信息。 通过阅读本书,读者不仅可以掌握C语言的基本语法和函数用法,还能了解如何在Linux环境中利用C语言进行系统级编程。这不仅有助于提升...
覆盖索引是指查询所需的所有数据都能从索引中直接获取,而无需回表到原始数据行,这能进一步提高查询性能。此外,过度使用索引也会带来负面影响,比如增加存储空间、影响插入和更新性能,因此需要在性能和成本之间...
4. 使用覆盖索引:覆盖索引可以避免访问表的数据行,从而提高查询效率。 5. 避免使用 LIKE 操作符:LIKE 操作符可能会导致索引失效,因此应该尽量避免使用 LIKE 操作符。 五、口诀 以下是一些常见的口诀: 1. 全...