InnoDB 記錄存儲(chǔ)結(jié)構(gòu)

InnoDB 將數(shù)據(jù)劃分為若干個(gè)頁,以頁作為磁盤和內(nèi)存之間交互的基本單位,InnoDB中頁大小一般為16KB。

系統(tǒng)變量innodb_page_size表明了InnoDB存儲(chǔ)引擎中的頁大小,默認(rèn)值為16384字節(jié),該變量只能在第一次初始化MySQL數(shù)據(jù)目錄指定,之后不能修改了。

InnoDB 記錄格式

COMPACT,REDUNDANT,DYNAMIC,COMPRESSED

可以在創(chuàng)建表指定使用的行格式

CREATE TABLE demo (
  c1 VARCHAR(10),
  c2 VARCHAR(10) NOT NULL,
  c3 CHAR(10),
  c4 VARCHAR(10)
) CHARSET=ascii ROW_FORMAT=COMPACT;

或者修改表的語句中指定使用的行格式

ALTER TABLE 表名 ROW_FORMAT=行格式名稱;
COMPACT 格式
image.png

先插入2組數(shù)據(jù):

SELECT * FROM demo;
+---------+---------+---------+---------+
|  c1         c2        c3       c4     |
+---------+---------+---------+---------+
| aaaa       bbb        cc       d      |
| eeee       fff        NULL     NULL   |
+---------+---------+---------+---------+
  • 變長(zhǎng)字段長(zhǎng)度列表
    MySQL 支持一些變長(zhǎng)的數(shù)據(jù)類型,比如VARCHAR,VARBINARY,各種TEXT類型,各種BLOB類型。這些數(shù)據(jù)列我們稱之為變長(zhǎng)字段。變長(zhǎng)字段中存儲(chǔ)多少字節(jié)的數(shù)據(jù)是不固定的,所以我們?cè)诖鎯?chǔ)真實(shí)數(shù)據(jù)的時(shí)候需要順便把這些數(shù)據(jù)占用的字節(jié)數(shù)也存儲(chǔ)起來。

    compact 行格式中,將其放在放在 變長(zhǎng)字段長(zhǎng)度列表中,各變長(zhǎng)字段的真實(shí)數(shù)據(jù)占用按照列的順序逆序存放。

    變長(zhǎng)字段列為 c1 c2 c4,按照列的順序逆序存放,所以第一條記錄的變長(zhǎng)字段長(zhǎng)度就是:01 03 04

    image.png
  • NULL 值列表
    一條記錄中某些列可能存儲(chǔ)NULL值,如果把這些NULL值都放到記錄的真實(shí)數(shù)據(jù)中存儲(chǔ)會(huì)很占地方,COMPACT 行格式把一條記錄中值為NULL的列統(tǒng)一管理起來,存儲(chǔ)到NULL值列表中,它的處理過程如下:

    • 首先統(tǒng)計(jì)表中允許存儲(chǔ)NULL的列有哪些 ?
      主鍵列以及使用NOT NULL修飾的列都是不可以存儲(chǔ) NULL 的值,所以在統(tǒng)計(jì)時(shí)不會(huì)把這些列算進(jìn)去。上面就是c1,c3,c4列。

    • 如果表中沒有允許存儲(chǔ)NULL的列,則NULL值列表也就不存在了,否則將每個(gè)允許存儲(chǔ)NULL的列對(duì)應(yīng)一個(gè)二進(jìn)制位,二進(jìn)制位為1表示該列的值為NULL,否則表示不為NULL。同時(shí)MySQL 規(guī)定NULL值列表必須用整數(shù)各字節(jié)的位表示,如果使用的二進(jìn)制位個(gè)數(shù)不是整數(shù)個(gè)字節(jié),則在字節(jié)的高位補(bǔ)0


      image.png

      所以上面的2條記錄NULL 值列表如下:

      image.png
  • 記錄頭信息
    記錄頭信息由固定的 5 字節(jié)組成,用于描述記錄的一些屬性。

    名稱 大小 描述
    預(yù)留位1 1 沒有使用
    預(yù)留位2 1 沒有使用
    deleted_flag 1 標(biāo)記該記錄是否被刪除
    min_re_flag 1 B+樹的每層非葉子節(jié)點(diǎn)中最小的目錄項(xiàng)都會(huì)添加該標(biāo)記
    n_owned
    heap_no
    record_type
    next_record
  • 記錄的真實(shí)數(shù)據(jù)
    對(duì)于表來說,記錄的真實(shí)數(shù)據(jù)除了自己定義的外,MySQL還會(huì)為每個(gè)記錄默認(rèn)添加一些列(也稱為隱藏列)。

    名稱 是否必需 占用空間 描述
    row_id 6字節(jié) 行ID,唯一標(biāo)識(shí)一條記錄
    trx_id 6字節(jié) 事務(wù)ID
    roll_pointer 7字節(jié) 回滾指針
    • InnoDB 主鍵生成策略
      • 優(yōu)先使用用戶自定義的主鍵為主鍵。
      • 如果用戶沒有定義主鍵,則選取一個(gè)不允許存儲(chǔ) NULL 值的 UNIQUE 健作為主鍵。
      • 如果表中連不允許存儲(chǔ) NULL 值的 UNIQUE 健都沒有,則InnoDB則會(huì)為表默認(rèn)添加一個(gè)row_id的隱藏列作為主鍵。
  • CHAR(M)列的存儲(chǔ)格式
    對(duì)于CHAR(M)類型的列來說,當(dāng)列采用的是定長(zhǎng)編碼的字符集時(shí),該列占用的字節(jié)數(shù)不會(huì)被加到變長(zhǎng)字段長(zhǎng)度列表中,但是如果采用變長(zhǎng)編碼的字符集時(shí),該列占用的字節(jié)數(shù)還是會(huì)被加到變長(zhǎng)字段長(zhǎng)度列表。

  • 溢出列

REDUNDANT

過時(shí)了,這里不分析。

DYNAMIC

DYNAMIC, COMPRESSED和 COMPACT 格式挺像的,只不過在處理溢出列的時(shí)候。

COMPRESSED

不同于DYNAMIC,COMPRESSED 行格式會(huì)采用壓縮算法對(duì)頁面進(jìn)行壓縮,以節(jié)省空間。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容