什么叫做覆蓋索引?
解釋一: 就是select的數據列只用從索引中就能夠取得,不必從數據表中讀取,換句話說查詢列要被所使用的索引覆蓋。
解釋二: 索引是高效找到行的一個方法,當能通過檢索索引就可以讀取想要的數據,那就不需要再到數據表中讀取行了。如果一個索引包含了(或覆蓋了)滿足查詢語句中字段與條件的數據就叫做覆蓋索引。
解釋三:是非聚集組合索引的一種形式,它包括在查詢里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆蓋查詢語句[select子句]與查詢條件[Where子句]中所涉及的字段,也即,索引包含了查詢正在查找的所有數據)。
不是所有類型的索引都可以成為覆蓋索引。覆蓋索引必須要存儲索引的列,而哈希索引、空間索引和全文索引等都不存儲索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引當發起一個被索引覆蓋的查詢(也叫作索引覆蓋查詢)時,在EXPLAIN的Extra列可以看到“Using index”的信息。
注:遇到以下情況,執行計划不會選擇覆蓋查詢。
①:select選擇的字段中含有不在索引中的字段,即索引沒有覆蓋全部的列。
②:where條件中不能含有對索引進行like的操作。
是否走索引,查詢示例如下:
CREATE TABLE `t_user` ( `id` bigint(100) NOT NULL AUTO_INCREMENT, `password` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `age` int(11) DEFAULT NULL, `nick_name` varchar(255) DEFAULT NULL, `sex` int(255) DEFAULT NULL, `birthday` datetime DEFAULT NULL, `class_id` int(11) DEFAULT NULL COMMENT '班級id', PRIMARY KEY (`id`), KEY `index_phone` (`phone`) USING BTREE, KEY `index_birthday` (`birthday`) USING BTREE, KEY `index_name` (`name`,`age`) USING BTREE # 聯合索引 ) ENGINE=InnoDB AUTO_INCREMENT=1588138958133 DEFAULT CHARSET=utf8;
1:如上圖所示:這次走的是覆蓋索引,因為索引中包含了要查詢的列字段,在聯合索引中,或者是單個索引,所要查詢的列的是索引的子集或者是相等,才能走覆蓋索引,否則是要回表的(列id主鍵除外)。但是需要注意的是靠左匹配查詢,這個是很重要的。在實際開發中,盡量使用覆蓋索引,減少回表的操作。
select age, name from t_user where age = '32' --- 走索引 覆蓋索引 select age from t_user where age = '32' ------- 走索引 覆蓋索引 select age, sex from t_user where age = '32' ------- 不走索引 全表掃描 select sex from t_user where age = '32' ------- 不走索引 全表掃描 select age, name from t_user where name = '32' ------- 走索引 覆蓋索引 select sex from t_user where name = '32' ------- 走索引 非覆蓋索引 select name,age, phone from t_user where name = '32' ------- 走索引 非覆蓋索引 select sex from t_user where name = '32' ------- 走索引 非覆蓋索引 select id from t_user where name = '32' ------- 走索引 覆蓋索引 select id from t_user where age = '32' ------- 走索引 覆蓋索引
總結:
①:在innodb存儲引擎中,分為主鍵索引和輔助索引。只有在主鍵索引中,葉子節點存儲的是數據記錄(一行行的數據),且數據是按照主鍵從小到大的順序進行排序。所以建議在排序的時候,排序字段最好也是創建索引,這樣減少數據在內存中的排序時間。輔助索引葉子節點存儲的是主鍵。
②:在innodb存儲引擎中,表一定要創建主鍵索引,否則在等值查詢中,會鎖住全表,而不是鎖住的某一行數據(行鎖)。
③:在innodb存儲引擎中,模糊查詢like "XX%"不一定會走索引,因為考慮到列的離散型,列離散型越大,會走索引的可能性會比較大。比如像"aa1","aa2"..."aan",是不會走索引的。
④:在innodb存儲引擎中,范圍查詢之后索引失效。比如index(name,age,phone), where name = 'guodong' and age > 20 and phone = '15317700182',這個時候只匹配name和age,phone是不會走索引的,原因也是列的離散型。
⑤:MySQL數據庫服務器執行器優化的,比如index(name,age),where age = 12 and name = 'guodong',這個時候也是會走索引的,但是會有一個性能開銷,所以還是最好是完全匹配。