1. 程式人生 > >聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index)

聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index)

索引的重要性 資料庫效能優化中索引絕對是一個重量級的因素,可以說,索引使用不當,其它優化措施將毫無意義。聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index) 最通俗的解釋是:聚簇索引的順序就是資料的物理儲存順序,而對非聚簇索引的索引順序與資料物理排列順序無關。舉例來說,你翻到新華字典的漢字“爬”那一頁就是P開頭的部分,這就是物理儲存順序(聚簇索引);而不用你到目錄,找到漢字“爬”所在的頁碼,然後根據頁碼找到這個字(非聚簇索引)。

聚簇索引的唯一性 正式聚簇索引的順序就是資料的物理儲存順序,所以一個表最多隻能有一個聚簇索引,因為物理儲存只能有一個順序。正因為一個表最多隻能有一個聚簇索引,所以它顯得更為珍貴,一個表設定什麼為聚簇索引對效能很關鍵。

非聚簇索引

索引節點的葉子頁面就好比一片葉子。葉子頭便是索引鍵值。

先建立一張表:

CREATE TABLE `user` ( 
`id` INT NOT NULL ,
`name` VARCHAR NOT NULL ,
`class` VARCHAR NOT NULL);

對於MYISAM引擎,如果建立 id 和 name 為索引。對於下面查詢:

select * from user where id = 1

會利用索引,先在索引樹中快速檢索到 id,但是要想取到id對應行資料,必須找到該行資料在硬碟中的儲存位置,因此MYISAM引擎的索引 葉子頁面上不僅儲存了主鍵id 還儲存著 資料儲存的地址資訊。如圖:

這裡寫圖片描述

像這樣的索引就稱為非聚簇索引。

非聚簇索引的二級索引與主鍵索引類似。假設我們對name新增索引,那麼name的索引樹葉子將是如下結構:

這裡寫圖片描述

聚簇索引

對於 非聚簇索引 來說,每次通過索引檢索到所需行號後,還需要通過葉子上的磁碟地址去磁碟內取資料(回行)消耗時間。為了優化這部分回行取資料時間,InnoDB 引擎採用了聚簇索引。  聚簇索引,即將資料存入索引葉子頁面上。對於 InnoDB 引擎來說,葉子頁面不再存該行對應的地址,而是直接儲存資料:

這裡寫圖片描述

這樣便避免了回行操作所帶來的時間消耗。 使得 InnoDB 在某些查詢上比 MyISAM 還要快!

ps. 關於查詢時間,一般認為 MyISAM 犧牲了功能換取了效能,查詢更快。但事實並不一定如此。多數情況下,MyISAM 確實比 InnoDB 查的快 。但是查詢時間受多方面因素影響。InnoDB 查詢變慢得原因是因為支援事務、回滾等等,使得 InnoDB的葉子頁面實際上還包含有事務id(換句話說就是版本號) 以及回滾指標。

在二級索引方面, InnoDB 與 MyISAM 有很大區別。

InnoDB預設對主鍵建立聚簇索引。如果你不指定主鍵,InnoDB會用一個具有唯一且非空值的索引來代替。如果不存在這樣的索引,InnoDB會定義一個隱藏的主鍵,然後對其建立聚簇索引。一般來說,InnoDB 會以聚簇索引的形式來儲存實際的資料,它是其它二級索引的基礎。

假設對 InnoDB 引擎上表name欄位加索引,那麼name索引葉子頁面則只會儲存主鍵id:

這裡寫圖片描述

檢索時,先通過name索引樹找到主索引id,再通過id在主索引樹的聚簇索引葉子頁面取出資料。