Mysql 目前有4種行格式:Redundant、Compact、Dynamic、Compressed
Version 5.6 已經默認使用 Compact
Version 5.7 默認使用Dynamic
Redundant 是比較老的數據格式,Compressed 不能應用在System data;所以Compact和Dynamic應用較廣泛;
規定(只討論InnoDB):
1、存儲單元為頁(page),16KB(16384B)
2、每頁至少需要存兩條數據
3、每條記錄都會有記錄頭
4、記錄幾乎都會有3個隱藏列(rowId,transactionId,rollPointer)
Compact:
變長字段(記錄的長度)列表 + NULL列表 + 記錄頭信息 + 列值
變長字段(記錄的長度)列表:
采用1-2個字節來表示一個字段的長度,逆序;
字段最大長度<= 255字節用1個字節表示;大於255字節,但是實際使用字節<=127,也使用1個字節來表示;其他情況使用2個字節來表示;
char如果是變長字符集(GBK、UTF8)也會需要使用變長字段列表來存儲字段使用的長度;
NULL列表:
逆序,存儲每條記錄中允許為NULL的字段,將實際為NULL的字段用1表示,實際不為NULL的字段用0表示;
每一列不是用一個字節來表示,而是用一個位來表示;
記錄頭信息:
使用5個字節來表示;
主要包含:該記錄是否被刪除,記錄類型,下一條記錄的相對偏移量;
Redundant:
字段長度偏移列表 + 記錄頭 + 列值
字段長度偏移列表,用來記錄每列的結束位置;
真實數據(整條記錄)<=127B 用1個字節記錄,其他使用2個字節;
是使用1個字節還是2個字節來存儲,該信息放在記錄頭的(1byte_offs_flag屬性上)
每個列記錄的第一個bit 使用來表示該列是否位NULL;
Dynamic:
與Compact行格式很像,差異在於頁面溢出的處理上;
Compressed:
在於Dynamic使用了壓縮算法;
頁溢出:
因為每頁16KB,至少存儲兩行,所以每行大概有8KB的數據;拋開記錄頭信息等,大致每列超過768B就會產生頁溢出;
Compact:
1、會將溢出的數據單獨放入一個頁;外加20B存儲額外頁的信息(plus the 20-byte pointer to the externally stored part)
2、索引可以使用前768B
Dynamic:
2、如果頁溢出,則使用20B存儲整個列信息(列數據都存儲在溢出頁上)(with the clustered index record containing only a 20-byte pointer to the overflow page)
3、可以使用前3072B字符的索引(--innodb-large-prefix決定)
總的說來,Redundant使用更多的字節數量來存儲一條記錄(字段長度偏移列表),頁溢出會使用更多的20B來表示溢出部分(或整列)數據,會使得索引數據更大;
參考:
https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html