以 MySQL 默認的存儲引擎 InnoDB 為例
InnoDB 包含以下四種行格式
- Compact
- Redundant
- Dynamic
- Compressed
指定行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名稱;
ALTER TABLE 表名 ROW_FORMAT=行格式名稱;
示例:
創建一張表,指定行格式為 Compact
CREATE TABLE test_table (
c1 VARCHAR(10),
c2 VARCHAR(10) NOT NULL,
c3 CHAR(10),
c4 VARCHAR(10)
CHARSET=ascii ROW_FORMAT=COMPACT;
行格式類型
Compact
Compact 中一條完整的記錄可以被分成 '記錄的額外信息' 和 '記錄的真實數據' 兩部分
記錄的額外信息
Compact 中記錄的額外信息包含三類:變長字段長度列表、NULL 值列表、記錄頭信息
變長字段長度列表
MySQL 支持一些變長的數據類型 (VARCHAR),這些數據在存儲時不僅要存儲數據內容,還需要將占用的字節數存儲起來
定長數據類型 (CHAR) 在以一些變長字符集儲存數據時,由於儲存長度為變長,所以也需要在該列表中存儲其長度
在記錄的開頭部位就是各個變長字段占用的字節數,這些數據逆序存放
如果表中沒有變長字段,就沒有變長字段長度列表
NULL 值列表
NULL 值列表存儲有表中所有 NULL 值,可以節約許多空間
值為 1 時,代表 NULL;值為 0 時,代表非 NULL。當位數不夠整數個字節的時候,在高位補 0
所有數據逆序存放
如果表中沒有允許儲存 NULL 值的列,就沒有 NULL 值列表
記錄頭信息
名稱 | 大小 (bit) | 描述 |
---|---|---|
預留位1 | 1 | 沒有使用 |
預留位2 | 1 | 沒有使用 |
delete_mask | 1 | 標記該記錄是否被刪除 |
min_rec_mask | 1 | B+樹的每層非葉子節點中的最小記錄都會添加該標記 |
n_owned | 4 | 表示當前記錄擁有的記錄數 |
heap_no | 13 | 表示當前記錄在記錄堆的位置信息 |
record_type | 3 | 表示當前記錄的類型,0 表示普通記錄,1 表示B+樹非葉子節點記錄,2 表示最小記錄,3 表示最大記錄 |
next_record | 16 | 表示下一條記錄的相對位置 |
記錄的真實數據
隱藏列
除了一些自定義列的數據外,MySQL 還會為每個記錄默認添加一些隱藏列:
列名 | 是否必須 | 占用空間 (bit) | 描述 |
---|---|---|---|
DB_ROW_ID | 否 | 6 | 行ID,唯一標識一條記錄 |
DB_TRX_ID | 是 | 6 | 事務ID |
DB_ROLL_PTR | 是 | 7 | 回滾指針 |
只有當用戶沒有指定主鍵,且表中沒有 Unique 鍵時才會添加 DB_ROW_ID
作為主鍵
儲存數據
當定長數據類型 (CHAR) 沒有儲存滿時,剩下的位都由空格 (0x20) 填滿
當使用變成字符集時,由於儲存字節長度不一定,當占用字節數少的字符串變為占用字節數多的字符串時需要新開辟一個空間,會產生存儲碎片
Redundant
記錄的額外信息
字段長度偏移列表
Redundant 行格式會把該條記錄中所有列 (包括隱藏列) 的長度信息都按照逆序存儲到 '字段長度偏移列表' 中
儲存的值為兩個相鄰數值的差值
所有數據逆序存放
記錄頭信息
名稱 | 大小 (bit) | 描述 |
---|---|---|
預留位1 | 1 | 沒有使用 |
預留位2 | 1 | 沒有使用 |
delete_mask | 1 | 標記該記錄是否被刪除 |
min_rec_mask | 1 | B+樹的每層非葉子節點中的最小記錄都會添加該標記 |
n_owned | 4 | 表示當前記錄擁有的記錄數 |
heap_no | 13 | 表示當前記錄在頁面堆的位置信息 |
n_field | 10 | 表示記錄中列的數量 |
1byte_offs_flag | 1 | 標記字段長度偏移列表中每個列對應的偏移量是使用1字節還是2字節表示的 |
next_record | 16 | 表示下一條記錄的相對位置 |
記錄的真實數據
存儲數據
不管該列使用的字符集是什么,只要是使用 CHAR 類型,占用的真實數據空間就是該字符集表示一個字符最多需要的字節數和字符串長度
例如使用 utf8 字符集的 CHAR(10) 列占用的真實數據空間始終是 30 個字節
Dynamic & Compressed
MySQL 8.0 中默認的行格式為 Dymatic
這兩個行格式與 Compact 只有在處理行溢出數據 (<- 點擊查看) 時有不同:它們不會在記錄真實數據處儲存真實數據的前 768 個字節,而是把所有的字節都存儲到其他頁面中,並且只儲存其他頁面的地址
Compressed 與 Dymatic 不同的一點是它會采用壓縮算法對頁面進行壓縮,以節省空間