深挖MySQL——innodb的運作過程(三)物理表空間

眾所周知,

想要清晰的瞭解一款軟體的運作原理,最重要的就是要了解它的物理結構、記憶體結構和內部執行緒執行分工。

下面讓我們一起來看看innodb的物理表空間的結構。

表空間又分為

公共表空間“ibdata”檔案

和表的

私有表空間“表名.ibd”檔案

,在私有表空間裡存放的資料只有表資料、索引、和插入緩衝Bitmap頁(描述插入緩衝的頁的資訊的頁,一個插入緩衝點陣圖頁可以追蹤16384個插入緩衝頁),其它資訊如回滾日誌、插入緩衝索引頁、二次寫緩衝等則儲存在公共表空間裡。

表空間的結構劃分為:

段、區(1M)、頁(預設16K,壓縮頁有8K、4K等。也有稱為塊)

頁為快取和磁碟的最小互動

單位。下圖為段、區、頁的結構:

深挖MySQL——innodb的運作過程(三)物理表空間

根據儲存的資料型別不同,段又可分為資料段、索引段、回滾段等。需要注意的是由於innodb表是B+樹索引組織的,索引即資料、資料即索引(B+樹相關下個篇張具體聊,現在現有個概念就行),

因此資料段存放的是B+樹的葉子節點資料頁和索引頁

,而

索引段儲存的並不是索引頁,而是B+樹的非葉子節點

。在innodb,段的管理是由innodb自身完成,我們對它稍作了解即可。

區由連續的頁組成,

正常情況下大小為1M

,為了寫入的時候更有可能的順序寫,一般innodb申請區空間的時候會一次性申請四五個區。

預設情況下頁的大小為16k,即一個區一般情況下由64個頁

。innodb1。0。x後引入了壓縮頁,出現了2k、4k、8k的頁,此時每個區對應的頁數為512、256、128,innodb1。2。x後引入了頁大小引數innodb_page_size,此後非壓縮也也可以為4k、8k。

為了節省磁碟開銷,

預設每個段開始時會先用32個頁大小的碎片頁來存放資料

,而後才會64個連續頁的申請空間。

頁時磁碟管理的最小單位,也是緩衝和磁碟互動的最小單位

,有些地方也稱為塊。常見的頁型別有:資料頁、undo頁、系統頁、事務資料頁、插入緩衝點陣圖頁、插入緩衝空閒列表頁、未壓縮的二進位制大物件頁、壓縮的二進位制大物件頁。

innodb是

面向行

的儲存引擎(row-oriented)。innodb的行結構除了業務欄位外,還有三個隱藏欄位:rowid(預設和主鍵值相同,沒有主鍵的話則自動生成),最後更新此資料的事務ID,回滾日誌指標(在聊多版本併發控制的時候細聊)。

innodb對行的記錄格式,也進行過多次的升級。可以輸入命令列show table status like ‘表名’;來看你的表的行記錄格式,5。7版本的MySQL預設是Dynamic。

innodb1。0。x之前,行記錄格式只有Redundant和Compact,Redundant是為了相容舊版的頁格式而出現的記錄格式,Compact對比Redundant,多了NULL標誌位,即相對NULL比較多的行Compact格式儲存的資料會比較緊湊。

innodb1。0。x版本後引入了Compressed行記錄格式和Dynamic行記錄格式,統稱Barracuda檔案格式,舊版的Redundant和Compact稱為Antelope檔案格式。新的格式對於blob型別的資料採用完全行溢位的存放方式:舊版的在行內也會儲存768個字首位元組的blob的資料,超出部分存放到大物件頁。新版的不管超不超出直接存放到大物件頁。

分割槽

最後聊一聊大家可能會關心的

表分割槽

,對於MySQL分割槽在MySQL層面完成。分割槽的原理即將一個表或索引拆分為多個更小、更可管理的部分,而對訪問資料庫的應用來說,在邏輯上只有一個表。MySQL只支援水平分割槽:Range分割槽、List分割槽、Hash分割槽、Key分割槽、子分割槽(在分割槽基礎上再進行分割槽),本質上都是根據主鍵(沒有主鍵第一個候選碼也行,沒有候選碼rowid也行)將行資料分佈在不同的分割槽,直觀看來就是一個表會出現多個。ibd檔案。

對於innodb來說,我個人理解,資料表還是不如不分割槽的好。假設一個表有1000w資料,對於主鍵查詢來說,拆分為10份100w資料的分割槽,查詢確實有速度的提升,但是對於非主鍵查詢來說就慘了,非主鍵查詢基本上要掃描所有10個分割槽,由於檔案的拆分,IO次數增加,查詢速度不升反降。因此對於分割槽的設計要小心小心再謹慎。

如有錯誤,敬請斧正;歡迎轉載,但請務必註明出處;最後,在此向神奇的海螺保證,

絕不太監

!!!