InnoDB索引實現

         對於InnoDB存儲引擎的表,記錄默認會按一定順序保存,如果有明確定義的主鍵,則按照主鍵順序保存。如果沒有主鍵,但是有唯一索引,就按照唯一索引的順序保存。如果既沒有主鍵也沒有唯一索引,表中會自動生成一個內部列,按照這個列的順序保存。按照主鍵或內部列的訪問是最快的,索引InnoDB表儘量自己指定主鍵,當表中同時有幾個列都是唯一的,都可以作爲主鍵的時候,要選擇最常作爲訪問條件的列作爲主鍵,提高查詢效率。另外,InnoDB表的普通索引都會保存主鍵的鍵值,這樣通過對索引加鎖就可以實現行級鎖。

         可以說數據庫必須有索引,沒有索引則檢索過程變成了順序查找,O(n)的時間複雜度幾乎是不能忍受的。我們非常容易想象出一個只有單關鍵字組成的表如何使用B+樹進行索引,只要將關鍵字存儲到樹的節點即可。當數據庫一條記錄裏包含多個字段時,一棵B+樹就只能存儲主鍵,如果檢索的是非主鍵字段,則主鍵索引失去作用,又變成順序查找了。這時應該在第二個要檢索的列上建立第二套索引。  這個索引由獨立的B+樹來組織。有兩種常見的方法可以解決多個B+樹訪問同一套表數據的問題,一種叫做聚簇索引(clustered index ),一種叫做非聚簇索引(secondary index)。這兩個名字雖然都叫做索引,但這並不是一種單獨的索引類型,而是一種數據存儲方式。對於聚簇索引存儲來說,行數據和主鍵B+樹存儲在一起,輔助鍵B+樹只存儲輔助鍵和主鍵,主鍵和非主鍵B+樹幾乎是兩種類型的樹。對於非聚簇索引存儲來說,主鍵B+樹在葉子節點存儲指向真正數據行的指針,而非主鍵。

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

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

         爲了更形象說明這兩種索引的區別,我們假想一個表如下圖存儲了4行數據。其中Id作爲主索引,Name作爲輔助索引。圖示清晰的顯示了聚簇索引和非聚簇索引的差異。

wKioL1goc1-gTq9CAALLwQwKAcg461.png-wh_50

聚簇索引優點:

1 查詢速度更快:由於行數據和葉子節點存儲在一起,這樣主鍵和行數據是一起被載入內存的,找到葉子節點就可以立刻將行數據返回了,如果按照主鍵Id來組織數據,獲得數據更快。

2 減少索引維護:輔助索引使用主鍵作爲"指針" 而不是使用地址值作爲指針的好處是,減少了當出現行移動或者數據頁分裂時輔助索引的維護工作,使用主鍵值當作指針會讓輔助索引佔用更多的空間,換來的好處是InnoDB在移動行時無須更新輔助索引中的這個"指針"。也就是說行的位置(實現中通過16KPage來定位,後面會涉及)會隨着數據庫裏數據的修改而發生變化(前面的B+樹節點分裂以及Page的分裂),使用聚簇索引就可以保證不管這個主鍵B+樹的節點如何變化,輔助索引樹都不受影響。

 

InnoDB行鎖的實現:

 

InnoDB的行鎖是加在索引上的,實現過程如下:

 

1.按輔助索引檢索:行鎖加在輔助索引對應的列,並根據主鍵項找到主鍵索引加鎖。

如上圖,按name字段檢索name='Ellision'Ellision索引列會加鎖,並在主鍵索引項14 加鎖。這樣當其他事務就無法訪問name='Ellision'列,也無法根據其他數據項訪問相應的數據列。


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