InnoDB頁結(jié)構(gòu)

Innodb以頁作為磁盤和內(nèi)存交互的基本單位,默認大小是16k。頁有各種各樣的類型,其中存儲真實用戶數(shù)據(jù)的頁稱為索引頁(以下簡稱為頁)。以下討論的頁,實際上是聚簇索引的葉子節(jié)點。

對于一些占用空間較大的列(比如varchar text blob類型等),不會把所有的數(shù)據(jù)都放在頁里,具體看行格式。
如果是COMPACT,對于占用空間較大的列,留一部分?jǐn)?shù)據(jù)在頁里,其他的放到溢出頁。
如果是DYNAMIC或者COMPRESSED,對于占用空間較大的列,不會留一部分?jǐn)?shù)據(jù)在頁里,全部放到溢出頁。
mysql 5.7默認行格式為DYNAMIC。

一個頁有7個組成部分,其中最主要的是空閑區(qū)(Free Space)、用戶記錄區(qū)(User Records)和頁目錄(Page Directory),其他的部分記錄了頁的一些基本信息,比如本頁已存了多少記錄,用戶記錄區(qū)的起始位置在本頁的偏移量等。

image.png

用戶記錄區(qū)(也叫堆)用于存儲真實的用戶數(shù)據(jù),每次新增一行記錄,都會從空閑區(qū)取一定空間,劃分到用戶記錄區(qū),直到空閑區(qū)空了,就判定本頁滿了。

每次刪除記錄,并不會真的把數(shù)據(jù)從頁里移除掉,而是加一個刪除標(biāo)記(每一行記錄都有若干空間存額外的信息,比如刪除標(biāo)記位),如果真的把數(shù)據(jù)從頁里移除掉,需要把其他的記錄往前移,并且需要修改偏移量,開銷太大。被刪除的記錄會組成一個垃圾鏈表,垃圾的鏈表的空間可以被覆蓋。

用戶記錄區(qū)中,記錄按主鍵從小到大排序,除了存儲真實的用戶數(shù)據(jù)行,還會有多余的兩行,分別是Infimum和Supremum,分別表示本頁的最小記錄和最大記錄。

每一條記錄都有一個指向下一行記錄的指針(實際上存的是當(dāng)前記錄到下一個記錄的距離,即字節(jié)數(shù)),也就是頁內(nèi)的記錄組成了一條單向鏈表,單向鏈表的第一個節(jié)點是Infimum,第二個節(jié)點是第一行真實數(shù)據(jù),第三個節(jié)點是第二行真實數(shù)據(jù)......倒數(shù)第二個節(jié)點是最后一行真實數(shù)據(jù),最后一個節(jié)點是Supremum。


image.png

如果每次從頁內(nèi)找記錄的時候,都從Infimum遍歷到Supremum,性能太差了,所以用戶記錄區(qū)又分為好幾個組,每個組有一個槽,記錄了本組最大的記錄在本頁的地址偏移量。

頁里的頁目錄,就是用于存儲槽。


image.png

每次從頁查找數(shù)據(jù)的時候,會先從頁目錄做二分查找,找到比待查找值大但是差值最小的槽,待查找值就在該槽對應(yīng)的組中。該槽的上一個槽對應(yīng)的記錄的下一行記錄,就是本組的第一行記錄,從這一行記錄開始遍歷本組,就能找到待查找的記錄。

頁的File Header(文件頭部)部分,存儲了本頁、上一個頁、下一個頁的頁號,也就是不同頁之間組成了雙向鏈表。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容