mysql的聚簇索引與非聚簇索引

在mysql數據庫中,myisam引擎和innodb引擎使用的索引類型不同,myisam對應的是非聚簇索引,而innodb對應的是聚簇索引

聚簇索引

所謂聚簇索引,就是指主索引文件和數據文件爲同一份文件,聚簇索引主要用在Innodb存儲引擎中。在該索引實現方式中B+Tree的葉子節點上的data就是數據本身,key爲主鍵,如果是一般索引的話,data便會指向對應的主索引。

innodb中,沒有主見索引,則會使用unique索引,沒有unique索引,則會使用數據庫內部的一個行的id來當作主鍵索引。

非聚簇索

非聚簇索引就是指B+Tree的葉子節點上的data,並不是數據本身,而是數據存放的地址。主索引和輔助索引沒啥區別,只是主索引中的key一定得是唯一的。主要用在MyISAM存儲引擎中。

INNODB和MYISAM的主鍵索引與二級索引的對比:

InnoDB的的二級索引的葉子節點存放的是KEY字段加主鍵值。因此,通過二級索引查詢首先查到是主鍵值,然後InnoDB再根據查到的主鍵值通過主鍵索引找到相應的數據塊。

而MyISAM的二級索引葉子節點存放的還是列值與行號的組合,葉子節點中保存的是數據的物理地址。所以可以看出MYISAM的主鍵索引和二級索引沒有任何區別,主鍵索引僅僅只是一個叫做PRIMARY的唯一、非空的索引,且MYISAM引擎中可以不設主鍵

具體示例:

  1. InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用"where id = 14"這樣的條件查找主鍵,則按照B+樹的檢索算法即可查找到對應的葉節點,之後獲得行數據。
  2. 若對Name列進行條件搜索,則需要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操作,最終到達葉子節點即可獲取整行數據。(重點在於通過其他鍵需要建立輔助索引)

MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什麼不同,節點的結構完全一致只是存儲的內容不同而已,主鍵索引B+樹的節點存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方,這兩顆B+樹的葉子節點都使用一個地址指向真正的表數據,對於表數據來說,這兩個鍵沒有任何差別。由於索引樹是獨立的,通過輔助鍵檢索無需訪問主鍵的索引樹。

表數據是和主鍵一起存儲的,主鍵索引的葉結點存儲行數據,二級索引的葉結點存儲行的主鍵值。

  • 由於行數據和葉子節點存儲在一起,同一頁中會有多條行數據,訪問同一數據頁不同行記錄時,已經把頁加載到了Buffer中,再次訪問的時候,會在內存中完成訪問,不必訪問磁盤。這樣主鍵和行數據是一起被載入內存的,找到葉子節點就可以立刻將行數據返回了,如果按照主鍵Id來組織數據,獲得數據更快。
  • 輔助索引使用主鍵作爲"指針"而不是使用地址值作爲指針的好處是,減少了當出現行移動或者數據頁分裂時輔助索引的維護工作,使用主鍵值當作指針會讓輔助索引佔用更多的空間,換來的好處是InnoDB在移動行時無須更新輔助索引中的這個"指針"。也就是說行的位置(實現中通過16K的Page來定位)會隨着數據庫裏數據的修改而發生變化(前面的B+樹節點分裂以及Page的分裂),使用聚簇索引就可以保證不管這個主鍵B+樹的節點如何變化,輔助索引樹都不受影響。
  • 聚簇索引適合排序,非聚簇索引不適合用在排序的場合。因爲聚簇索引本身已經是按照物理順序放置的,排序很快。非聚簇索引則沒有按序存放,需要額外消耗資源來排序。

    當你需要取出一定範圍內的數據時,用聚簇索引也比用非聚簇索引好。

  • 可以把相關數據保存在一起。例如實現電子郵箱時,可以根據用戶 ID 來聚集數據,這樣只需要從磁盤讀取少數的數據頁就能獲取某個用戶的全部郵件。如果沒有使用聚簇索引,則每封郵件都可能導致一次磁盤 I/O。

缺點

1)插入速度嚴重依賴於插入順序,按照主鍵的順序插入是最快的方式,否則將會出現頁分裂,嚴重影響性能。因此,對於InnoDB表,我們一般都會定義一個自增的ID列爲主鍵。

2)更新主鍵的代價很高,因爲將會導致被更新的行移動。因此,對於InnoDB表,我們一般定義主鍵爲不可更新。

3)二級索引訪問需要兩次索引查找,第一次找到主鍵值,第二次根據主鍵值找到行數據。

4)二級索引的葉節點存儲的是主鍵值,而不是行指針(非聚簇索引存儲的是指針或者說是地址),這是爲了減少當出現行移動或數據頁分裂時二級索引的維護工作,但會讓二級索引佔用更多的空間。

5)聚簇索引主鍵的插入速度要比非聚簇索引主鍵的插入速度慢很多。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章