1. 程式人生 > 其它 >【MySQL學習筆記(四)】之 InnoDB的四種行格式介紹,溢位列

【MySQL學習筆記(四)】之 InnoDB的四種行格式介紹,溢位列

技術標籤:MYSQLmysql資料庫

本文章由公號【開發小鴿】釋出!歡迎關注!!!


老規矩–妹妹鎮樓:

一. InnoDB頁

(一) 頁的概述

InnoDB是一個將表中的資料儲存到磁碟上的儲存引擎,真正處理資料的過程發生在記憶體中,需要把磁碟中的資料載入到記憶體中,如果處理寫入或修改請求,還需要把記憶體中的內容重新整理到磁碟上。InnoDB將資料劃分為若干項,以頁作為磁碟和記憶體之間互動的基本單位,頁大小一般為16KB,即16384位元組,可在初始化MySQL資料目錄時指定,之後無法修改。

(二) InnoDB行格式

1. 概述

以記錄為單位向表中插入資料,這些記錄在磁碟上的存放形式被稱為行格式。InnoDB上有4中行格式,COMPACT, REDUNDANT, DYNAMIC, COMPRESSED。可在建立或修改表的語句中指定記錄所使用的行格式:

CREATE TABLE 表名(列的資訊) ROW_FORMAT=行格式;
ALTER TABLE 表名 ROW_FORMAT=行格式;

2. COMPACT行格式

一條完整的記錄分為記錄的額外資訊和記錄的真實資料兩部分。

(1) 記錄的額外資訊

這部分資訊是為了更好地管理記錄而額外新增的資訊,分為三部分,變長欄位長度列表,NULL值列表,記錄頭資訊。

1) 變長欄位長度列表

MySQL支援一些變長的資料型別,如VARCHAR, VARBINARY, TEXT等等,變長欄位能夠儲存多少位元組的資料是不固定的,因此在儲存真實資料的同時還要儲存這些資料佔用的位元組數。所有的變長欄位佔用的位元組數按照列的順序的逆序存放到變長欄位長度列表中。如果變長欄位所採用的字符集 最多需要W個位元組來表示一個字元,而該變長欄位在初始化時設定最多儲存M個字元,那麼該變長欄位最多佔用的位元組數就是W x M,如果 W x M 《 255,則使用1個位元組來表示真實資料佔用的位元組數;如果 W x M > 255,且真實位元組數L <= 127,則使用1個位元組,否則使用兩個位元組。

注意,變長欄位長度列表中只儲存值為非NULL的列的內容長度!

2) NULL值列表

為了節省NULL值的儲存空間,將一條記錄中值為NULL的列統一管理起來,儲存到NULL值列表中。

首先統計表中允許儲存NULL的列有哪些,主鍵列和使用NOT NULL修飾的列都是不可以儲存NULL值的。如果表中沒有允許儲存NULL的列,那麼NULL值列表就不會存在了,否則將每個允許儲存NULL的列對應一個二進位制位,二進位制位按照列的順序逆序排列。當某個二進位制位為1時,表示該列的值為NULL,否則不為NULL。MySQL規定NULL值列表必須使用整數個位元組的位表示,如果使用的二進位制位個數不是整數個位元組,則在位元組的高位補齊0。


3) 記錄頭資訊

記錄頭資訊由固定的5個位元組組成,用於描述記錄的一些屬性,具體的概念請到書中檢視。

(2) 記錄的真實資料

記錄的真實資料除了自己定義的列的資料外,還會為每個記錄預設新增一些隱藏列。InnoDB表中優先使用使用者自定義的主鍵作為主鍵,如果沒有定義主鍵,則選取一個不允許儲存NULL值的UNIQUE鍵作為主鍵,如果連這個鍵都沒有,則InnoDB會預設新增一個row_id的隱藏列作為主鍵。trx_id為隱藏的事務ID列,roll_pointer為隱藏的回滾指標列。

定長的列即時只儲存很小的值,也會佔用固定的位元組數,NULL值直接儲存在前面的NULL值列表處,在記錄的真實資料處就不會冗餘儲存了,節省了儲存空間。


(3) CHAR(M)的儲存格式

CHAR(M) 表示定長的欄位,如果該欄位採用的是定長編碼字符集,如ascii,則它的長度不會儲存到變長欄位長度列表中;若該欄位採用的是變長編碼的字符集,如utf8, gbk,則它的長度也會儲存到變長欄位長度列表中。

採用變長編碼字符集的CHAR(M) 型別的列要求至少佔用M個位元組,而VARCHAR(M)沒有這個要求,比如utf8字符集,對於CHAR(10),該列儲存的資料佔用的位元組長度為10 – 30 位元組,因為最多有10個字元,而一個字元佔用1-3個位元組。這種設計可以在更新記錄時直接更新,而不會由於儲存空間不夠而重新分配空間,導致原有的記錄空間稱為碎片。


3. REDUNDANT行格式

比較古老的一種行格式。

(1) 欄位長度偏移列表

將該條記錄中所有列(包括隱藏列)的長度資訊都按照逆序儲存到欄位長度偏移列表中,且使用兩個相鄰偏移量的差值來計算各個列值的長度。


(2) 偏移量的位元組數

每個列對應的偏移量使用1個位元組還是2個位元組來儲存,是通過記錄的真實資料佔用的位元組數大於127還是小於127判斷的。只要整條記錄的真實資料佔用的位元組長度大於127,即時某個列的值佔用的儲存空間不大於127位元組,也要使用兩個位元組來表示該列的偏移量。這是一種過時的方法,浪費空間。

(3) NULL值的處理

REDUNDANT行格式中並沒有NULL值列表,因此將列對應的偏移量值的第一個位元作為是否是NULL的依據,該位元位稱為NULL位元位。

如果儲存NULL值的欄位是定長型別的,則NULL值將佔用記錄的真實資料部分,並把該欄位對應的資料用0x00位元組填充;如果是變長資料型別,則不佔用記錄的真實資料空間。

4. 溢位列

在COMPACT和REDUNDANT行格式中,記錄都會被分配到某個頁中儲存,如果記錄的大小超過了頁的大小,則記錄的真實資料處只會儲存該列的一部分資料,而把剩餘的資料分散在幾個其他的頁中,然後在記錄的真實資料處使用20個位元組儲存指向這些頁的地址。

如果某一列的資料非常多,則在該記錄的真實資料處只會儲存該列前768位元組的資料以及一個指向其他頁的地址,其他頁稱為溢位頁,這個列稱為溢位列。

5. 產生溢位頁的臨界點

一個列在儲存了多少位元組後才會變為溢位列呢?

MySQL規定一個頁中至少存放兩行記錄,每個頁中除了存放我們的資訊,還有額外的資訊,加起來需要132位元組的空間,每個記錄需要的額外資訊時27位元組,假設一個列的真實資料佔用的位元組數為n,如果該列不會發生溢位現象,則需要滿足以下不等式:

132 + 2 x (27 + n) < 16384

即 n < 8099

6. DYNAMIC行格式

溢位時,不會儲存該列的前768個位元組,而是將所有位元組儲存到溢位頁中。

7. COMPRESSED行格式

使用壓縮演算法歲頁面進行壓縮,節省空間。

只有REDUNDANT行格式是非緊湊的,是過時的,其他的都是較新的行格式,是緊湊的。