覆盖索引
如果索引的叶子节点中已经包含要查询的字段的值,称为覆盖索引。
1.索引条目通常小于数据行的大小,所以如果只需要读取,那么MySQL就会极大地减少数据访问量。因为对缓存负载非常重要,这种情况下响应时间大部分花费在数据拷贝上。
2.索引按照列值顺序存储的,所以对于I/O 密集型的范围查询会比随机从磁盘读取每一行数据I/O要少的多。
3.一些存储引擎如MyISAM 在内存中只缓存索引,数据则依赖于操作系统来缓存,因此要访问数据需要一次系统调用。这可能导致严重的性能问题,尤其那些调用占用了数据访问中最大开销的场景。
4.MySQL 只能使用B-Tree索引做覆盖引,不同存储引擎实现覆盖索引的方式也不同。
Create Table
CREATE TABLE `inventory` (
`inventory_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`film_id` smallint(5) unsigned NOT NULL,
`store_id` tinyint(3) unsigned NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`inventory_id`),
KEY `idx_fk_film_id` (`film_id`),
KEY `idx_store_id_film_id` (`store_id`,`film_id`),
CONSTRAINT `fk_inventory_film` FOREIGN KEY (`film_id`) REFERENCES `film` (`film_id`) ON UPDATE CASCADE,
CONSTRAINT `fk_inventory_store` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4582 DEFAULT CHARSET=utf8mb4
EXPLAIN SELECT store_id ,film_id FROM inventory ;发起索引覆盖的查询 可以查看到Using index
explain select * from products where actor ='SEAN_CARRY' and title '%APPLLO%';
MySQL 不能在索引中执行like 操作。MySQL 能在索引中做最左前缀匹配的like比较,因为该操作可以转换为比较简单的比较操作,但是如果是通配符开头的like 查询,存储引擎就无法作比较,这种情况下,MySQL 府二区只能提前数据行的值而不是索引值来做比较。
解决方法:延迟关联, 先将索引覆盖三个数据列(attist,title,prod_id)。延迟对列的访问,在查询的第一个阶段MySQL 可以
使用覆盖索引,在from 子句的子查询中找到匹配的prod_id,
explain select * from products join ( select pro_id from products where actor='SEAN CARRY' AND title like '%APPOLLO%');