InnoDB表空間文件結構分為: Tablespace(表空間) --> Segment(段)-->Extent(區)-->Page(頁)--> Row(行)
1) Tablesapce
2) 段 (Segment)
3) 區 ( Extend )
1. 區是由連續頁組成的空間,每個區的默認大小都是1MB,一個區中有64個連續的頁。為了保證區中頁的連續性,擴展的時候InnoDB存儲引擎一次從磁盤申請4~5個區。
4) 頁 (Page)
5) 行 (Row)
Page是整個InnoDB存儲的最基本構件,也是InnoDB磁盤管理的最小單位,與數據庫相關的所有内容都存儲在這種Page結構裡。
Page分為幾種類型,常見的頁類型有數據頁(B tree Node)Undo頁(Undo Log Page)系統頁(System Page) 事務數據頁(Transaction System Page)等;
頁結構整體上可以分為三大部分,分别為通用部分(文件頭、文件尾)、存儲記錄空間、索引部分。
1) 通用部分 (File Header&File Trailer )
通用部分 : 主要指文件頭和文件尾,将頁的内容進行封裝,通過文件頭和文件尾校驗的CheckSum方式來确保頁的傳輸是完整的。
其中比較重要的是在文件頭中的 FIL_PAGE_PREV 和 FIL_PAGE_NEXT 字段,通過這兩個字段,我們可以找到該頁的上一頁和下一頁,實際上所有頁通過兩個字段可以形成一條雙向鍊表
2) 記錄部分(User Records&Free Space)
頁的主要作用是存儲記錄,所以“最小和最大記錄”和“用戶記錄”部分占了頁結構的主要空間。另外空閑空間是個靈活的部分,當有新的記錄插入時,會從空閑空間中進行分配用于存儲新記錄
3)數據目錄部分 (Page Directory)
數據頁中行記錄按照主鍵值由小到大順序串聯成一個單鍊表(頁中記錄是以單向鍊表的形式進行存儲的),且單鍊表的鍊表頭為最小記錄,鍊表尾為最大記錄。并且為了更快速地定位到指定的行記錄,通過 Page Directory 實現目錄的功能,借助 Page Directory 使用二分法快速找到需要查找的行記錄。
表的行格式決定了它的行是如何物理存儲的,這反過來又會影響查詢和DML操作的性能。如果在單個page頁中容納更多行,查詢和索引查找可以更快地工作,緩沖池中所需的内存更少,寫入更新時所需的I/O更少。
InnoDB存儲引擎支持四種行格式:Redundant、Compact、Dynamic 和 Compressed .
查詢MySQL使用的行格式,默認為: dynamic
mysql> show variables like 'innodb_default_row_format';
--------------------------- ---------
| Variable_name | Value |
--------------------------- ---------
| innodb_default_row_format | dynamic |
--------------------------- ---------
指定行格式語法
CREATE TABLE <table_name(column_name)> ROW_FORMAT=行格式名稱
ALTER TABLE <table_name> ROW_FORMAT=行格式名稱
Compact 設計目标是高效地存儲數據,一個頁中存放的行數據越多,其性能就越高。
compact行記錄由兩部分組成: 記錄放入額外信息 和 記錄的真實數據;
1、記錄額外信息部分
服務器為了描述一條記錄而添加了一些額外信息(元數據信息),這些額外信息分為3類,分别是: 變長字段長度列表、NULL值列表和記錄頭信息。
變長字段長度列表
MySQL支持一些變長的數據類型,比如varchar(M)、VARBINARY(M)、各種TEXT類型,各種BLOB類型,這些變長的數據類型占用的存儲空間分為兩部分:
變長字段的長度是不固定的,所以在存儲數據的時候要把這些數據占用的字節數也存起來,讀取數據的時候才能根據這個長度列表去讀取對應長度的數據。
在 Compact 行格式中,把所有變長類型的列的長度都存放在記錄的開頭部位形成一個列表,按照列的順序逆序存放,這個列表就是 變長字段長度列表。
NULL值列表
表中的某些列可能會存儲NULL值,如果把這些NULL值都放到記錄的真實數據中會比較浪費空間,所以Compact行格式把這些值為NULL的列存儲到NULL值列表中。( 如果表中所有列都不允許為 NULL,就不存在NULL值列表 )
記錄頭信息
記錄頭信息是由固定的5個字節組成,5個字節也就是40個二進制位,不同的位代表不同的意思,這些頭信息會在後面的一些功能中看到。
1. delete_mask
這個屬性标記着當前記錄是否被删除,占用1個二進制位,值為0 的時候代表記錄并沒有被删除,為1 的時候代表記錄被删除掉了;
2. min_rec_mask
B 樹的每層非葉子節點中的最小記錄都會添加該标記。
3. n_owned
代表每個分組裡,所擁有的記錄的數量,一般是分組裡主鍵最大值才有的。
4. heap_no
在數據頁的User Records中插入的記錄是一條一條緊湊的排列的,這種緊湊排列的結構又被稱為堆。為了便于管理這個堆,把記錄在堆中的相對位置給定一個編号——heap_no。所以heap_no這個屬性表示當前記錄在本頁中的位置。
5. record_type
這個屬性表示當前記錄的類型,一共有4種類型的記錄, 0 表示普通用戶記錄, 1 表示B 樹非葉節點記錄, 2 表示最小記錄, 3 表示最大記錄。
6. next_record
表示從當前記錄的真實數據到下一條記錄的真實數據的地址偏移量,可以理解為指向下一條記錄地址的指針。值為正數說明下一條記錄在當前記錄後面,為負數說明下一條記錄在當前記錄的前面。
2、記錄真實數據部分
記錄的真實數據除了插入的那些列的數據,MySQL會為每個記錄默認的添加一些列(也稱為隐藏列),具體的列如下:
生成隐藏主鍵列的方式有:
什麼是行溢出 ?
MySQL中是以頁為基本單位,進行磁盤與内存之間的數據交互的,我們知道一個頁的大小是16KB,16KB = 16384字節.而一個varchar(m) 類型列最多可以存儲65532個字節,一些大的數據類型比如TEXT可以存儲更多。
如果一個表中存在這樣的大字段,那麼一個頁就無法存儲一條完整的記錄.這時就會發生行溢出,多出的數據就會存儲在另外的溢出頁中。
總結: 如果某些字段信息過長,無法存儲在B樹節點中,這時候會被單獨分配空間,此時被稱為溢出頁,該字段被稱為頁外列。
Compact中的行溢出機制
InnoDB 規定一頁至少存儲兩條記錄(B 樹特點),如果頁中隻能存放下一條記錄,InnoDB存儲引擎會自動将行數據存放到溢出頁中。
當發生行溢出時,數據頁隻保存了前768字節的前綴數據,接着是20個字節的偏移量,指向行溢出頁。
1. DYNAMIC 和 COMPRESSED 行記錄格式
DYNAMIC 和 COMPRESSED新格式引入的功能有:數據壓縮、增強型長列數據的頁外存儲和大索引前綴。
Compressed 和 Dynamic 行記錄格式與 Compact 行記錄格式是類似的,區别是在處理行溢出時,數據頁不會存儲真實數據的前768字節(完全溢出),隻存儲20個字節的指針來指向溢出頁。
Compressed 與 Dynamic 相比,Compressed 存儲的行數據會以zlib的算法進行壓縮以節省空間,因此對于 BLOB、TEXT、VARCHAR 這類大長度類型的數據能夠進行非常有效的存儲。
MySQL5.7 默認的行記錄格式是 Dynamic 。
2. Redundant
Redundant是 MySQL5.0 版本之前 InnoDB 的行記錄存儲方式。
Redundant 行記錄格式的首部是一個字段長度偏移列表,同樣是按照列的順序逆序放置的。該條記錄中所有列(包括隐藏列、NULL值列)的長度信息都按照逆序存儲到字段長度偏移列表。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!