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=============