多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
通常大家都会根据查询的where条件来创建合适的索引,不过这只是索引优化的一个方面.设计优秀的索引应该考虑到整个查询,而不单单是where条件部分.索引确实是一种查询数据的高效方式.但是mysql也可以使用索引来直接获取列的数据,这样就不再需要读取数据行.如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢? 如果一个索引包含(或者覆盖)所有需要查询的字段的值,我们就称为"覆盖索引" 覆盖索引是非常有用的工具,能够极大的提高性能,考虑下如果查询只需要扫描索引而无需回表,会带来多少好处: * 索引条目通常远小于数据行大小,所以如果只需要读取索引,那mysql就会极大地减少数据访问量.这对缓存的负载非常重要,因为这种情况下响应时间大部分花费在数据拷贝上.覆盖索引对于IO密集型的应用也有帮助,因为索引比数据更小,更容易放到内存中(对于myisam,他能压缩索引) * 因为索引是按照列值顺序存储的(至少在单个页内是如此).所以对于IO密集型的范围查询会比随机从磁盘读取每一行数据的IO要少的多.对于某些存储引擎,例如myisam和XtraDB,甚至可以用OPTIMIZE命令使得索引完全顺序排列,这让简单的范围查询能使用完全顺序的索引访问 * 一些存储引擎如myisam在内存中只缓存索引,数据则依赖于操作系统来缓存,因为要访问数据需要一次系统调用.这可能会导致严重的性能问题,尤其是那些系统调用占了数据访问中的最大开销场景 * 由于Innodb的聚簇索引,覆盖索引对Innodb表特别有用,Innodb的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询 在这些场景中,在索引中满足查询的成本一般比查询行要小很多 不是所有类型的索引都可以成为覆盖索引.覆盖索引必须要存储索引列的值,而哈希索引,空间索引和全文索引等都不存储索引列的值,所以mysql只能使用B-Tree索引做覆盖索引.另外,不同的存储引擎实现覆盖索引的方式也不同,而且不是所有的引擎都支持覆盖索引 当发起一个被索引覆盖的查询(也叫索引覆盖查询),在explain的extra列可以看到Using index的信息.例如:表sakila.inventory有一个多列索引(store_id,film_id).mysql如果只需访问这两列,就可以使用这个索引做覆盖索引 ![](https://box.kancloud.cn/13e5e797c5d98ac27915e411cef76e02_541x253.png) (很容易把extra列的Using index和type列的index搞混淆.其实这两者完全不同,type列和覆盖索引毫无关系,它只是表示这个查询访问数据的方式,或者说mysql查找行的方式) 索引覆盖还有很多陷阱可能会导致无法实现优化.mysql查询优化器会在执行查询钱判断是否有一个索引能进行覆盖 假设索引覆盖了where条件中的字段,但不是整个查询涉及的字段.如果条件为假,mysql5.5和更早的版本也总是会回表获取数据行,尽管并不需要这一行且最终会被过滤掉