模糊查詢下(like)如何使用覆蓋索引優化
在MySQL中,like ‘string%’可以用到索引,但是like ‘%string%’卻會全表掃描。這個是常識,但真的就沒有解決方法了嗎?有的,要使用到索引覆蓋。
什麼叫覆蓋索引?
-
解釋一: 就是select的資料列只用從索引中就能夠取得,不必從資料表中讀取,換句話說查詢列要被所使用的索引覆蓋。
-
解釋二: 索引是高效找到行的一個方法,當能通過檢索索引就可以讀取想要的資料,那就不需要再到資料表中讀取行了。如果一個索引包含了(或覆蓋了)滿足查詢語句中欄位與條件的資料就叫做覆蓋索引。
-
解釋三:是非聚集組合索引的一種形式,它包括在查詢裡的Select、Join和Where子句用到的所有列(即建立索引的欄位正好是覆蓋查詢語句[select子句]與查詢條件[Where子句]中所涉及的欄位,也即,索引包含了查詢正在查詢的所有資料)。
總之,不是所有型別的索引都可以成為覆蓋索引。覆蓋索引必須要儲存索引的列,而雜湊索引、空間索引和全文索引等都不儲存索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引
小試牛刀
CREATE TABLE a1
(
id INT AUTO_INCREMENT PRIMARY KEY,
column_name VARCHAR(20),
column_type VARCHAR(20)
);
CREATE INDEX idx_a1_column_name ON a1(column_name);
語句1:它沒有使用到索引(Extra:using where),意味著全表掃描,理論如此,
語句2:它使用了索引範圍查詢(type=range)(key=idx_a1_column_name),但是它使用索引方式為二級檢索(Extra:Using index condition)還是會有一定的效能消耗的,也有解決辦法:針對select的列建立聯合索引
語句3:它使用了索引覆蓋(Extra:Using index)
結論:
- using index :使用覆蓋索引的時候就會出現
- using where:在查詢使用索引的情況下,需要回表去查詢所需的資料
- using index condition:查詢使用了索引,但是需要回表查詢資料
- using index & using where:查詢使用了索引,但是需要的資料都在索引列中能找到,所以不需要回表查詢資料
有實驗證明using index & using where要優於using index condition。
小知識點(原理)
1.啥是回表?
上面講過如果索引的列在select子句中就不需要回表,索引列也是表,如果索引中包括你需要的列,查詢結果就找到了,如果沒有你需要的列,索引列中有指標指向表記錄的行位置,從表中查詢列值。
2.二級索引篇
聚簇索引:每個InnoDB表具有一個特殊的索引稱為聚集索引。如果您的表上定義有主鍵,該主鍵索引是聚集索引。如果你不定義為您的表的主鍵 時,MySQL取第一個唯一索引(unique)而且只含非空列(NOT NULL)作為主鍵,InnoDB使用它作為聚集索引。如果沒有這樣的列,InnoDB就自己產生一個這樣的ID值,它有六個位元組,而且是隱藏的,使其作為聚簇索引。
二級索引:又稱輔助索引、非聚集索引(no-clustered index)。b+tree樹結構,然而二級索引的葉子節點不儲存記錄中的所有列,其葉子節點儲存的是<健值,(記錄)地址>,非葉子節點存放的記錄格式為<鍵值,主鍵值,地址>。而聚集索引葉子節點儲存儲存記錄中的所有列,非葉子節點儲存的是下一層節點地址。
記錄的地址一般可以儲存兩種形式:
1. 記錄的實體地址,頁號:槽號:偏移量
2 . 記錄的主鍵值
innodb引擎是索引組織表,所有記錄都放在聚集索引裡,因此其輔助索引中的記錄地址存放的主鍵的鍵值。
讀操作:
通過二級索引查詢記錄僅能得到主鍵值,要查詢完整的記錄還需要再通過一次聚集索引查詢,這種查詢方式為書籤查詢(bookmark lookup)。
寫操作:
僅當主鍵發生改變時,才會更新二級索引。