以 MySQL 默認的存儲引擎 InnoDB 爲例
InnoDB 包含如下四種行格式html
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 中一條完整的記錄能夠被分紅 '記錄的額外信息' 和 '記錄的真實數據' 兩部分sql
Compact 中記錄的額外信息包含三類:變長字段長度列表、NULL 值列表、記錄頭信息指針
MySQL 支持一些變長的數據類型 (VARCHAR),這些數據在存儲時不只要存儲數據內容,還須要將佔用的字節數存儲起來
定長數據類型 (CHAR) 在以一些變長字符集儲存數據時,因爲儲存長度爲變長,因此也須要在該列表中存儲其長度
在記錄的開頭部位就是各個變長字段佔用的字節數,這些數據逆序存放
若是表中沒有變長字段,就沒有變長字段長度列表code
NULL 值列表存儲有表中全部 NULL 值,能夠節約許多空間
值爲 1 時,表明 NULL;值爲 0 時,表明非 NULL。當位數不夠整數個字節的時候,在高位補 0
全部數據逆序存放
若是表中沒有容許儲存 NULL 值的列,就沒有 NULL 值列表htm
名稱 | 大小 (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 還會爲每一個記錄默認添加一些隱藏列:blog
列名 | 是否必須 | 佔用空間 (bit) | 描述 |
---|---|---|---|
DB_ROW_ID | 否 | 6 | 行ID,惟一標識一條記錄 |
DB_TRX_ID | 是 | 6 | 事務ID |
DB_ROLL_PTR | 是 | 7 | 回滾指針 |
只有當用戶沒有指定主鍵,且表中沒有 Unique 鍵時纔會添加 DB_ROW_ID
做爲主鍵事務
當定長數據類型 (CHAR) 沒有儲存滿時,剩下的位都由空格 (0x20) 填滿
當使用變成字符集時,因爲儲存字節長度不必定,當佔用字節數少的字符串變爲佔用字節數多的字符串時須要新開闢一個空間,會產生存儲碎片ci
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 個字節
MySQL 8.0 中默認的行格式爲 Dymatic
這兩個行格式與 Compact 只有在處理行溢出數據 (<- 點擊查看) 時有不一樣:它們不會在記錄真實數據處儲存真實數據的前 768 個字節,而是把全部的字節都存儲到其餘頁面中,而且只儲存其餘頁面的地址 Compressed 與 Dymatic 不一樣的一點是它會採用壓縮算法對頁面進行壓縮,以節省空間