深入理解InnoDB(1)—行的存储结构
1.InnoDB頁的簡介
頁(Page)是 Innodb 存儲(chǔ)引擎用于管理數(shù)據(jù)的最小磁盤單位。常見的頁類型有數(shù)據(jù)頁、Undo 頁、系統(tǒng)頁、事務(wù)數(shù)據(jù)頁等
2.InnoDB行的存儲(chǔ)格式
我們插入MySQL的記錄在InnoDB中可能以4中行格式存儲(chǔ),分別是Compact、Redundant、Dynamic和Compressed行格式,我們可以在創(chuàng)建或修改表的語句中指定我們想要的行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名稱ALTER TABLE 表名 ROW_FORMAT=行格式名稱2.1 COMPACT行格式
Compact行記錄是在MySQL5.0中引入的,為了高效的存儲(chǔ)數(shù)據(jù),簡單的說,就是為了讓一個(gè)頁(Page)存放的行數(shù)據(jù)越多,這樣性能就越高
一條完整的記錄被分為記錄的額外信息和記錄的真實(shí)數(shù)據(jù)兩大部分
2.1.1 記錄的額外信息
這些額外信息分為3類,分別是變長字段長度列表、NULL值列表和記錄頭信息。
2.1.1.1 變長字段長度列表
逆序記錄每一個(gè)列的長度,如果列的長度小于 255 字節(jié),則使用一個(gè)字節(jié),否則使用 2 個(gè)字節(jié)。該字段的實(shí)際長度取決于列數(shù)和每一列的長度,因此是變長的
2.1.1.2 NULL值列表
一個(gè)字節(jié),表示該行是否有 NULL 值。注意:此處需要注意固定長度 CHAR 數(shù)據(jù)類型和變長 VCHAR 數(shù)據(jù)類型在 Compact 記錄下為 NULL 時(shí)不占用任何存儲(chǔ)空間。
2.1.1.3 記錄頭信息
用于描述記錄的記錄頭信息,它是由固定的5個(gè)字節(jié)組成。5個(gè)字節(jié)也就是40個(gè)二進(jìn)制位,不同的位代表不同的意思,其中 next_record 記錄了下一條記錄的相對(duì)位置,一個(gè)頁中的所有記錄使用這個(gè)字段形成了一條單鏈表。
2.1.2 記錄的真實(shí)數(shù)據(jù)
MySQL會(huì)為每個(gè)記錄默認(rèn)的添加一些列,除了記錄每一列對(duì)應(yīng)的數(shù)據(jù)外,還有隱藏列,它們分別是 Transaction ID、Roll Pointer 以及 row_id(當(dāng)沒有指定主鍵)
2.1.2.1 row_id
當(dāng)用戶沒有設(shè)置主鍵,并且沒有unique屬性時(shí),innoDB會(huì)隱式的生成一個(gè)row_id,作為主鍵
2.1.2.2 transaction_id 和 roll_pointer
用來記錄當(dāng)前記錄的事務(wù)號(hào),用于可重復(fù)讀隔離級(jí)別的樂觀鎖實(shí)現(xiàn)
2.2 Redundant行格式
MySQL5.0之前的行記錄格式:
2.2.1 字段長度偏移列表
與 Compact 中的變長字段長度列表相同的是它們都是按照列的逆序順序設(shè)置值的,不同的是字段長度偏移列表記錄的是偏移量,每一次都需要加上上一次的偏移,同時(shí)對(duì)于 CHAR 的 NULL 值,會(huì)直接按照最大空間記錄,而對(duì)于 VCHAR 的 NULL 值不占用任何存儲(chǔ)空間。
與compact行格式的不同在于:
- 存儲(chǔ)的是所有屬性的長度
- 長度是通過兩個(gè)相鄰偏移量的差計(jì)算得出的
- 使用了每個(gè)列對(duì)應(yīng)偏移量的第一位作為NULL比特位來標(biāo)記空值,并且對(duì)于真實(shí)記錄為NULL的定長字段也要使用0比特填充,變長則不用
- 對(duì)于char(M)來說,即使使用變長字符集,通通按照字符集的最大字符長度來分配空間
2.2.2 記錄頭信息
和compact的大致相同
行溢出數(shù)據(jù)
我們知道數(shù)據(jù)頁的大小是 16KB,Innodb 存儲(chǔ)引擎保證了每一頁至少有兩條記錄,當(dāng)行記錄的長度沒有超過行記錄最大長度時(shí),所有數(shù)據(jù)都會(huì)存儲(chǔ)在當(dāng)前頁。如果一頁當(dāng)中的記錄過大,會(huì)截取前 768 個(gè)字節(jié)存入頁中,其余的放入 BLOB Page。
然后記錄的真實(shí)數(shù)據(jù)處用20個(gè)字節(jié)存儲(chǔ)指向這些頁的地址(當(dāng)然這20個(gè)字節(jié)中還包括這些分散在其他頁面中的數(shù)據(jù)的占用的字節(jié)數(shù)),從而可以找到剩余數(shù)據(jù)所在的頁
2.3 Dynamic和Compressed行格式
InnoDB1.0x開始引入心的文件格式(file format,用戶可以理解位新的頁格式)——Barracuda,這個(gè)新的格式擁有兩種新的行記錄格式:Compressed和Dynamic。
新的兩種記錄格式對(duì)于存放BLOB中的數(shù)據(jù)采用了完全的行溢出的方式。
-
Dynamic行格式,列存儲(chǔ)是否放到off-page頁,主要取決于行大小,他會(huì)把行中最長的一列放到off-page,直到數(shù)據(jù)頁能存放下兩行。TEXT或BLOB列<=40bytes時(shí)總是存在于數(shù)據(jù)頁。這種方式可以避免compact那樣把太多的大列值放到B-tree Node(數(shù)據(jù)頁中只存放20個(gè)字節(jié)的指針,實(shí)際的數(shù)據(jù)存放在Off Page中,之前的Compact 和 Redundant 兩種格式會(huì)存放768個(gè)字前綴字節(jié))。
-
Compressed物理結(jié)構(gòu)上與Dynamic類似,Compressed行記錄格式的另一個(gè)功能就是存儲(chǔ)在其中的行數(shù)據(jù)會(huì)以zlib的算法進(jìn)行壓縮,因此對(duì)于BLOB、TEXT、VARCHAR這類大長度數(shù)據(jù)能夠進(jìn)行有效的存儲(chǔ)(減少40%,但對(duì)CPU要求更高)。
總結(jié)
以上是生活随笔為你收集整理的深入理解InnoDB(1)—行的存储结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 179. 最大数(排序
- 下一篇: 人为什么会梦到从未见过的人