MySQL聯合索引原理解析

什麼是MySQL聯合索引

聯合索引又叫複合索引,是MySQL的InnoDB引擎中的一個索引方式,若是一個系統頻繁地使用相同的幾個字段查詢結果,就能夠考慮創建這幾個字段的聯合索引來提升查詢效率。優化

如何創建索引

舉個例子:code

create table `table_name`(
 `id` bigint(20) NOT NULL  PRIMARY KEY,
  `a` int(11),
  `b` int(11),
  `c` varchar(22),
   KEY `key_a_b_c` (`a`,`b`,`c`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

如上面的代碼其中blog

KEY `key_a_b_c` (`a`,`b`,`c`)

語句就是創建了a,b,c字段聯合索引的語句。索引

最左前綴原則

在使用聯合索引時要注意有個最左前綴原則,最左前綴原則就是要考慮查詢的字段的順序,只有遵照這個原則才能最大地提升查詢的效率,下面咱們舉個例子說明最左前綴原則。內存

創建 (a,b,c)的聯合索引table

#徹底按建立的順序,能走到a,b,c3個字段的索引,評級:優化最高
SELECT * FROM tz_prod.table_name where a = 1 and b=2 and c = '3';
#換了b和c的順序,MySQL會進行優化,效率和上面的同樣,評級:優化最高
SELECT * FROM tz_prod.table_name where a = 1 and c = '3' and b=2;
#能走到a和b的索引,評級:優化最高
 SELECT * FROM tz_prod.table_name where    a = 1 and b=2 ;
#能走到a和b的索引,b的範圍查詢不影響優化,評級:優化最高
 SELECT * FROM tz_prod.table_name where     a = 1 and b<2 ;
#能走到a的索引,評級:優化最高
SELECT * FROM tz_prod.table_name where    a = 1;
#能走到a的索引,評級:優化最高
SELECT * FROM tz_prod.table_name order by   a ;
#只能走到a的索引走不到c的索引,若是c的離散度高則查詢效率很低,評級:優化差
SELECT * FROM tz_prod.table_name where     a = 1 and  c = '3';
#能走到a和b的索引走不到c的索引,b的範圍查詢使後面字段沒法走索引,評級:優化差
SELECT * FROM tz_prod.table_name where     a = 1  and b<2 and  c = '3';
#能走到a的索引,評級:優化最高
SELECT * FROM tz_prod.table_name where   a > 1  order by a;
#能走到a的索引,走不到b索引 評級:優化差
SELECT * FROM tz_prod.table_name where   a > 1  order by b;
#同上,評級:優化差
SELECT * FROM tz_prod.table_name where   a > 1  order by c;
#走不到b和c的索引,最左前綴原則必須以創建索引的第一個字段做爲第一個條件,評級:最差
SELECT * FROM tz_prod.table_name where   b=2 and  c = '3';

聯合索引提升查詢效率的原理

MySQL會爲InnoDB的每一個表創建聚簇索引,若是表有索引會創建二級索引。聚簇索引以主鍵創建索引,若是沒有主鍵以表中的惟一鍵創建,惟一鍵也沒會以隱式的建立一個自增的列來創建。聚簇索引和二級索引都是一個b+樹,b+樹的特色是數據按必定順序存在葉子節點且每頁數據相連。通常狀況下使用索引查詢時,先查詢二級索引的b+樹,查到數據並拿數據中保存的主鍵回查聚簇索引查到全部數據。下面咱們舉個例子來重現這個過程。效率

如下面表舉例,假設表中已經存了部分數據:原理

create table `user_info`(
  `id` bigint(20) NOT NULL  PRIMARY KEY,
  `name` varchar(11),
  `age` int(11),
  `phone` varchar(20),
   KEY `key_name_age` (`name`,`age`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

InnoDB創建的聚簇索引和二級索引以下圖im

聚簇索引

二級索引

假如咱們想要查找名字爲zhaoliu,年齡爲30的人的信息。即name='zhaoliu',age=30數據

  • (1)先查二級索引,先用二分法查找發如今wangwu名字的右邊
  • (2)讀取右邊的這頁的數據到內存,二分法查到數據2個name爲zhaoliu人。
  • (3)繼續二分法比較age查到數據id=31
  • (4)id=31回查聚簇索引先用二分法查找發如今31右邊
  • (5)讀取31左邊這頁數據到內存,二分法查到數據並返回數據

若是你僅僅查找id,name和age數據那麼這樣就用到了覆蓋索引,這樣就不用回查聚簇索引,在第(3)步直接返回數據便可。

相關文章
相關標籤/搜索