如何讓mysql索引更快一點

在 InnoDB 中,從二級索引回到主鍵索引查詢數據,這個過程稱做回表過程,並且這個回表過程是能夠被優化的,這個優化就是利用覆蓋索引mysql

先說結論,若是一個索引的字段包含了全部要查詢的字段,這個索引就稱做覆蓋索引,覆蓋索引能夠減小回表過程,能有效提升查詢效率sql

前面咱們有說過,在 InnoDB 中數據都是保存在 B+ 樹上,主鍵索引保存了整行記錄,二級索引保存了主鍵的值。bash

一次查詢操做,要麼是遍歷主鍵索引,要麼是遍歷二級索引,要麼就是先遍歷二級索引獲得主鍵 id 的值,而後再到主鍵索引上經過主鍵 id 查找知足要求的記錄。測試

若是隻遍歷一次 B+ 樹就能獲取到咱們要的數據,即沒有回表過程,這個效率顯然是不錯的,這就是覆蓋索引的優點。下面看個具體的例子。優化

mysql> create table user(
id int(11) primary key, 
name varchar(20) not null, 
age int(11),
sex int(11),
index (age)) engine=InnoDB;
複製代碼

依然是新建一個表,建立索引,插入一些測試數據,注意這裏只是爲了解釋說明覆蓋索引,並不表示 mysql 的真實執行方式,由於會涉及到 mysql 的優化器機制,這裏暫且不說了,之後再寫。ui

1    bob 16  1
2    kom 19  0
3    gum 18  1
4    tt  20  1
5    yy  25  1
複製代碼

建立一個 user 表,給 age 字段添加一個二級索引,並插入上面五條數據,而後看下面這條查詢語句。spa

select name from user where age between 18 and 21
複製代碼

咱們來分析下這條 sql 的執行過程:設計

1、age 字段上有索引,mysql 會先到 age 字段的 B+ 樹上找到知足條件的第一個葉子節點(age=19),這個葉子節點上保存了對應主鍵 id 的值 2,而後再到主鍵索引上找到 id 爲 2 的這條記錄,同時把 name 字段拿出來。code

2、重複第一步的操做,繼續從 age 索引上的葉子節點日後遍歷找出知足條件的第二個葉子節點,一樣回到主鍵上拿出 name 字段的值,直到遍歷到不知足條件的葉子節點(age=25)。索引

也就是說,這條 sql 語句雖然用到了索引,可是 age 索引上並無要查詢的 name 字段,因此只能回表到主鍵索引上查出 name 字段,因此這個過程實際上是遍歷了個兩個 B+ 樹。

那麼咱們刪除 age 這個單列索引,建立一個覆蓋索引 (age,name), 把要查詢的 name 字段也添加到索引中來。

#刪除原索引
drop INDEX age on USER
#新建覆蓋索引
ALTER TABLE USER add index age_name(age,name)
複製代碼

因爲如今這個覆蓋索引上的字段包含了要查詢的 age 和 name 字段,免去了到主鍵索引上查詢數據的過程,其實也就是隻遍歷了一個 B+ 樹,能夠大大提高查詢效率。

添加索引雖然能提高查詢效率,但索引也是須要佔用額外空間的,並且索引還須要維護成本,因此一般加不加索引須要根據實際需求來權衡。

總之,在設計索引或者優化 sql 語句的時候,要儘可能避免回表操做,因此使用覆蓋索引是一種經常使用的 sql 優化手段。

因此咱們平時寫 sql 語句的時候,select 後面只寫查詢須要用到的字段,去掉不須要的字段,避免回表操做。

有問題歡迎你們留言交流,原創不易,若是文章對你有幫助,歡迎點贊,感謝支持。

相關文章
相關標籤/搜索