MySQL高性能的索引策略(三)mysql
使用覆盖索引sql
若是索引包含知足查询的全部数据,就称为覆盖索引。覆盖索引是一种很是强大的工具,能大大提升查询性能。只须要读取索引而不用读取数据有如下一些优势:缓存
(1)索引项一般比记录要小,因此MySQL访问更少的数据;服务器
(2)索引都按值的大小顺序存储,相对于随机访问记录,须要更少的I/O;工具
(3)大多数据引擎能更好的缓存索引。好比MyISAM只缓存索引。性能
(4)覆盖索引对于InnoDB表尤为有用,由于InnoDB使用汇集索引组织数据,若是二级索引中包含查询所需的数据,就再也不须要在汇集索引中查找了。优化
覆盖索引不能是任何索引,只有B-TREE索引存储相应的值。并且不一样的存储引擎实现覆盖索引的方式都不一样,并非全部存储引擎都支持覆盖索引(Memory和Falcon就不支持)。spa
覆盖索引的实际应用,以下表结构,code
CREATE TABLE people ( id int not null AUTO_INCREMENT, last_name varchar(50) not null, first_name varchar(50) not null, dob date not null, gender enum('m', 'f') not null, primary key (id), key(last_name, first_name, dob) );
以下查询,explain,索引
> explain select id , last_name , first_name from people ******************** 1. row ********************* id: 1 select_type: SIMPLE table: people type: index possible_keys: key: last_name key_len: 107 ref: rows: 1 Extra: Using index 1 rows in set
能够看到Extra列是 Using index,因此只在二级索引中就找到了须要的数据,不要再去聚簇索引中根据主键查找须要的数据行。
可是要注意的是否是全部的类型的索引均可以成为覆盖索引。覆盖索引必需要存储索引列的值,而哈希索引,空间索引和全文索引等都不存储索引列的值,索引mysql只能使用
B-Tree索引作覆盖索引。另外,不一样的存储引擎实现覆盖索引的方式也不一样,并且不是全部的引擎都支持覆盖索引。
咱们再来看下面这种状况。假设索引覆盖了WHERE条件中的字段,但不是整个查询涉及的字段。
> explain select * from people where last_name = 'hello' and first_name like '&hello&' ******************** 1. row ********************* id: 1 select_type: SIMPLE table: people type: range possible_keys: last_name key: last_name key_len: 104 ref: rows: 1 Extra: Using index condition 1 rows in set
好,看到了吧,出现了using index condition,先把mysql的ICP(索引条件推送)优化关掉,
set optimizer_switch = 'index_condition_pushdown=off';
> explain select * from people where last_name = 'hello' and first_name like '&hello&' ******************** 1. row ********************* id: 1 select_type: SIMPLE table: people type: range possible_keys: last_name key: last_name key_len: 104 ref: rows: 1 Extra: Using where 1 rows in set
这里的索引没法覆盖该查询,有两个缘由:
没有任何索引覆盖这个查询。由于查询从表中选择了全部的列,而没有任何索引覆盖了全部的列。
mysql不能在索引中执行like操做。这是底层存储引擎API的限制。由于若是是通配符开头的like查询,存储引擎就没法比较匹配。这种状况下,mysql服务器只能提取数据行的值而不是索引的值来作比较。
=============END=============