知識點:
- mysql創(chuàng)建主鍵:
- 首先判斷表中是否有非空的唯一索引,如果有,則該列為主鍵
- 如果不符合上述條件,存儲引擎會自動創(chuàng)建6個字節(jié)大小的指針
- 當(dāng)表中有多個非空唯一索引,會按照索引的順序選擇第一個索引作為主鍵
InnoDB邏輯存儲結(jié)構(gòu)
先看邏輯圖:
圖1
- 表空間Tablespace(ibd文件)
- 段Segment(一個索引2個段)
- 區(qū)Extent(1MB):64個Page
- 頁Page(16KB):磁盤管理的最小單位
- 一個B+樹節(jié)點就是一個頁(16KB)
- 頁的編號可以映射到物理文件偏移
- B+樹葉子節(jié)點前后形成雙向鏈表
圖2
- 行Row
- 字段Field
InnoDB Page詳細講解
- 基本概念:
- Page的默認(rèn)大小為16KB,每個Page用32位的數(shù)字標(biāo)記,因此一共有2^32個Page,每個表空間一共有64TB的容量。
- 每個Page都有一個offset,page0的offset為0,而page1的offset為16384(16KB)。
-
Page的結(jié)構(gòu)為下圖所示:
Page結(jié)構(gòu)
從圖中看出,每個Page有38字節(jié)頭和8字節(jié)的尾。FIL頭和尾的結(jié)構(gòu)如下所示:
Header和Trailer
每個Page占用16KB,64個連續(xù)的Page放在一起一共占用1MB,稱為一個Extent,多個Extent組合在一起就是一個表空間,也叫表文件,如下圖所示:
Space File
InnoDB索引結(jié)構(gòu)存儲(從Page角度理解):
-
頁:存儲的最小單位,InnoDB使用32位比特來表示一個頁號,因此InnoDB能保存的最大容量為(2^32)*16KB。
圖3
如圖所示:每個頁保存前一頁和后一頁的指針,各4個字節(jié)。此外頁頭信息還包括頁類型和頁號。
圖4
從圖中看出,頁中間存放著數(shù)據(jù)庫中的數(shù)據(jù)記錄,其中第一條記錄是系統(tǒng)記錄,Supermum用來保存數(shù)據(jù)記錄的尾指針,而Infimum用來保存數(shù)據(jù)記錄的頭指針。User Record在頁中以單鏈表的形式存儲。
圖5
記錄和Page組合起來就是完整的數(shù)據(jù)格式。見下圖所示:
圖6
User Record可以分為四種格式: - 主索引樹的非葉子節(jié)點:非葉子節(jié)點保存主鍵和指針
- 主索引樹的葉子節(jié)點:葉子節(jié)點保存主鍵,并且保存主鍵記錄
- 輔助索引的非葉子節(jié)點:保存非主鍵鍵值,以及指針
- 輔助索引的葉子節(jié)點:保存非主鍵鍵值,以及主鍵(通過主鍵查詢獲取記錄)
圖7
下面看看主鍵索引的結(jié)構(gòu)圖,只包含主鍵非葉子節(jié)點索引和主鍵葉子節(jié)點索引。
圖8
從B+樹的角度理解InnoDB索引存儲:
InnoDB B+樹索引主要有葉子節(jié)點和非葉子節(jié)點兩種類型。葉子節(jié)點包含數(shù)據(jù),非葉子節(jié)點只包含指針。
-
葉子節(jié)點:
圖9 -
非葉子節(jié)點:
圖10
從圖中可以看出,非葉子節(jié)點中保存的是最小鍵值子節(jié)點的Page值,而葉子節(jié)點中保存的是數(shù)據(jù)記錄。B+樹是平衡樹,同一層可以有多個節(jié)點,稱為兄弟節(jié)點,兄弟節(jié)點之間通過雙向鏈表連接。如下圖葉子節(jié)點,在同一層次:
圖11
下面舉個例子來看B+樹一個root節(jié)點的結(jié)構(gòu):
圖12
則B+樹數(shù)據(jù)結(jié)構(gòu)如下圖所示:
圖13
如果數(shù)據(jù)量變多,則B+樹會增加到多層:
圖14