MySQL 聚簇索引 和覆蓋索引

nicce發表於2018-12-08

一.聚簇索引
1.聚簇索引並不是一種單獨所以,而是一種資料儲存方式。
InnoDB 的聚簇索引實際上在同一結構中儲存了B-Tree 索引和資料行。

2.當表有聚簇索引時,它的資料行實際上存放在索引的葉子頁中。“聚簇”表示資料行和相鄰的鍵值緊湊的儲存在一起。

3.對應InnoDB 來說如果表沒有定義主鍵,會選擇一個唯一的非空索引代替。如果沒有這樣的索引InnoDB 會隱式定義一個主鍵來作為聚簇索引。InnoDB 只聚集在同一頁面中的記錄。

4.聚簇索引的優勢:

(1)可以把相關資料儲存在一起。
(2)資料訪問更快。資料和索引儲存在同一個 B-Tree 。
(3)使用覆蓋索引掃描的查詢可以直接使用頁節點的主鍵值

5.聚簇索引的缺點:

(1)聚簇索引最大的提高了I/O密集型應用的效能,但如果資料全部都放到記憶體中,則資料的順序就沒有那麼重要了,聚簇索引也就沒什麼優勢了。

(2)插入速度嚴重依賴插入順序。按照主鍵插入的方式是InnoDB 速度最快的方式,但如果不是按照主鍵順序載入資料,那麼在載入後最好使用OPTIMIZE TABLE 命令重新組織一2下表
(3)更新聚簇索引列的代價很高。因為會強制InnoDB 將每個被更新的行移動到新的位置

6.二級索引

主鍵索引的葉子節點存的是整行資料,在InnoDB 裡,主鍵索引也被稱為聚簇索引

非主鍵索引的葉子節點內容是主鍵的值。在InnoDB 裡。非主鍵索引也被稱為二級索引。
如:select* from order where user_id=3; user_id是普通索引。則會先搜尋user_id 的索引樹,得到id=5,再到id 索引樹搜尋一次,這個過程就是 “回表”。
也就是說非主鍵索引需要查詢2次

二.覆蓋索引
1.mysql 可以使用索引直接來獲取列的資料,這樣就可以不再需要讀取資料行。
如果索引的葉子節點中已經包含要查詢的資料,那麼還有什麼必要再回表查詢呢?如果一個索引包含(覆蓋)所有要查詢的欄位的值,那麼就稱為“覆蓋索引”

2.覆蓋索引可以提高查詢的效能,不需要會表,好處是:

(1)索引條目通常小於資料行,如果只需讀取索引,那麼mysql 就會減少訪問量
(2)索引是按照列值順序儲存的,索引I/O 密集型的範圍查詢會比隨機從磁碟讀取每一行資料的I/O 要少得多
(3)一些儲存引擎如MyISAM 在記憶體只快取索引,資料則依賴作業系統來快取,因此要訪問資料需要一次系統呼叫,這可能導致嚴重的效能問題,尤其是那些系統呼叫佔了資料訪問中最大開銷的場景
(4)InnoDB 的聚簇索引,覆蓋索引對InnoDB 表的特別有用。InnoDB 的二級索引在葉子節點儲存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。

3
select id from order where user_id between 1 and 3
這時候只需要查ID 的值,而ID 已經在user_id 索引樹上,因此可以直接提供查詢結果,不需要回表。

select * from order where user_id between 1 and 3
一旦用了select *,就會有其他列需要讀取,這時在讀完index以後還需要去讀data才會返回結果。

這兩種處理方式效能差異非常大,特別是返回行數比較多,並且讀資料需要 I/O 的時候,可能會有幾十上百倍的差異。因此建議根據需要用select *

ps:文章參考《高效能mysql》一書

相關文章