MySQL之InnoDB引擎中的Compact行格式用法
1、背景
mysql中數(shù)據(jù)存儲(chǔ)是存儲(chǔ)引擎干的事,InnoDB存儲(chǔ)引擎以頁為單位存儲(chǔ)數(shù)據(jù),每個(gè)頁的大小為16KB,平時(shí)我們操作數(shù)據(jù)庫(kù)都是以行為單位進(jìn)行增刪改查,行數(shù)據(jù)是存儲(chǔ)在頁上的,行的格式有4種:Compat、Redundant、Dynamic、Compressed,今天我們來講一下Compat行格式。
2、數(shù)據(jù)示例
我們建表語句中使用的varchar、text、blob等類型不確定長(zhǎng)度的就使用了Compact行格式,為了方便理解我們手動(dòng)創(chuàng)建一個(gè)表并且插入兩條記錄,后面都結(jié)合這兩條記錄來進(jìn)行Compat行格式講解,表和記錄如下:
- 創(chuàng)建表
CREATE TABLE test_compact ( id INT AUTO_INCREMENT PRIMARY KEY, str1 VARCHAR(255) NOT NULL DEFAULT '', str2 VARCHAR(255), str3 CHAR(5) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT=COMPACT;
- 插入數(shù)據(jù)
INSERT INTO test_compact (str1, str2, str3) VALUES ('AA', 'BB', 'CCC'), ('AAA', NULL, NULL);
- 查看數(shù)據(jù)
mysql [xxx]> select * from test_compact; +----+------+------+------+ | id | str1 | str2 | str3 | +----+------+------+------+ | 1 | AA | BB | CCC | | 2 | AAA | NULL | NULL | +----+------+------+------+ 2 rows in set (0.001 sec)
- 查看表的行格式
mysql [xxx]> show table status like 'test_compact' \G; *************************** 1. row *************************** Name: test_compact Engine: InnoDB Version: 10 Row_format: Compact //目前表使用的行格式 Rows: 2 Avg_row_length: 8192 Data_length: 16384 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: 3 Create_time: 2024-12-13 17:20:47 Update_time: 2024-12-13 17:21:02 Check_time: NULL Collation: utf8mb4_general_ci Checksum: NULL Create_options: row_format=COMPACT //創(chuàng)建表時(shí)指定的格式 Comment: Max_index_length: 0 Temporary: N 1 row in set (0.001 sec)
3、Compact解釋
【1】組成
Compact行格式組成圖如下:
Compact行由頭部信息+隱藏行+數(shù)據(jù)列三部分組成。
- 頭部信息:由三部分組成,可變長(zhǎng)度列的實(shí)際長(zhǎng)度信息、列是否為NULL信息、描述記錄信息。
- 隱藏列:有三列,DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR,后面詳細(xì)講解。
- 數(shù)據(jù)列:每一列的值。
【2】頭部信息
頭部信息可以如圖表示:
接下來就結(jié)合上面創(chuàng)建的test_compact表和插入的記錄進(jìn)行理解。
可變長(zhǎng)度列指的就是表中的str1和str2字段,因?yàn)閟tr1和str2長(zhǎng)度不固定,所以需要額外花費(fèi)空間來記錄str1和str2的長(zhǎng)度,str1和str2的值只有不為NULL的時(shí)候才需要記錄長(zhǎng)度,并且str1和str2長(zhǎng)度的順序是根據(jù)列順序的逆序來存放。
存放str1和str2長(zhǎng)度大小為1個(gè)或者2個(gè)字節(jié),判斷方法是:可變字段存儲(chǔ)的最大字節(jié)>255字節(jié)并且真實(shí)存儲(chǔ)的字節(jié)數(shù)>127字節(jié)就使用2個(gè)字節(jié)存儲(chǔ)長(zhǎng)度,否則使用1個(gè)字節(jié)存儲(chǔ)長(zhǎng)度。
可變字段存儲(chǔ)的最大字節(jié)=varchar(n)里的n * 字符集的最大字節(jié)數(shù)。n代表的是字符數(shù),而我們用的utf8mb4字符集1個(gè)字符用1~4個(gè)字節(jié)表示,可以用如下命令看:
mysql [xxx]> show charset like 'utf8mb4'; +---------+---------------+--------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+---------------+--------------------+--------+ | utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 | +---------+---------------+--------------------+--------+ 1 row in set (0.001 sec)
可以看到utf8mb4可以表示的一個(gè)字符最大字節(jié)為4,所以str1和str2列可以存儲(chǔ)的最大字節(jié)數(shù)為255 * 4 = 4080,ASCII字符只占用1個(gè)字節(jié),第一條記錄中的str1和str2實(shí)際長(zhǎng)度都為2個(gè)字節(jié)。
同樣的str3的類型為CHAR(5),根據(jù)字符集決定存它儲(chǔ)字節(jié)的范圍為5~20,所以str3的長(zhǎng)度信息也需要進(jìn)行存儲(chǔ)。
第一條記錄str3內(nèi)容’CCC’長(zhǎng)度看起來雖然為3,實(shí)際上長(zhǎng)度為5,這是為了防止更新str3為大于3小于5的數(shù)據(jù)時(shí),以前的空間就成為了空間碎片需要釋放。
可以用下圖表示上面2條記錄長(zhǎng)度的存儲(chǔ)信息:
可以為NULL列表指的就是沒有NOT NULL修飾的str2和str3列,用二進(jìn)制的0和1來表示列是否為NULL值,0代表非NULL,1代表NULL,根據(jù)列的順序逆序排列NULL信息,必須用二進(jìn)制的整數(shù)倍來存儲(chǔ)NULL信息,不足1字節(jié)高位補(bǔ)0,上面2條記錄的NULL信息如下:
行記錄描述信息是由5個(gè)字節(jié)也就是40個(gè)二進(jìn)制位組成,不同位代表不同的含義,不做過多解釋。
【3】隱藏列
InnoDB存儲(chǔ)引擎會(huì)為每一行數(shù)據(jù)額外分配三個(gè)列:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR,通過表格來理解一下:
隱藏列 | 描述 | 大小 |
---|---|---|
DB_ROW_ID | 唯一標(biāo)識(shí) | 6字節(jié) |
DB_TRX_ID | 事務(wù)id | 6字節(jié) |
DB_ROLL_PTR | 指向要回滾數(shù)據(jù)的地址 | 7字節(jié) |
DB_ROW_ID只有主鍵和unique健都不存在時(shí),InnoDB存儲(chǔ)引擎會(huì)創(chuàng)建一個(gè)大小為6字節(jié)作為隱藏主鍵id使用。
【4】數(shù)據(jù)列
數(shù)據(jù)列只需要注意值為NULL的列不需要再去花空間去存儲(chǔ),因?yàn)轭^部信息的NULL列表已經(jīng)存儲(chǔ)了是否為NULL,所以上面2條記錄完整表示如下:
4、總結(jié)
本篇文章講了Compact行格式組成,其它幾種格式都差不多,Redundant會(huì)記錄所有列的長(zhǎng)度信息,通過相鄰列的偏移量來計(jì)算列的長(zhǎng)度;Dynamic、Compressed格式在行溢出(列數(shù)據(jù)過于大頁面存不下)時(shí)列數(shù)據(jù)只存儲(chǔ)其它頁的地址,數(shù)據(jù)全存儲(chǔ)在其它頁通過鏈表連接;Compact和Redundant會(huì)在當(dāng)前頁存儲(chǔ)一部分?jǐn)?shù)據(jù)信息和在其它頁的剩余數(shù)據(jù)地址。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL不用like+%實(shí)現(xiàn)模糊查詢
本文主要介紹了MySQL不用like+%實(shí)現(xiàn)模糊查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01ubuntu server配置mysql并實(shí)現(xiàn)遠(yuǎn)程連接的操作方法
下面小編就為大家分享一篇ubuntu server配置mysql并實(shí)現(xiàn)遠(yuǎn)程連接的操作方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12實(shí)現(xiàn)mysql級(jí)聯(lián)復(fù)制的方法示例
這篇文章主要介紹了實(shí)現(xiàn)mysql級(jí)聯(lián)復(fù)制的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05mysql數(shù)據(jù)存儲(chǔ)過程參數(shù)實(shí)例詳解
這篇文章主要介紹了mysql數(shù)據(jù)存儲(chǔ)過程參數(shù)實(shí)例詳解,小編覺得挺不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-10-10mysql主從基于docker和django實(shí)現(xiàn)讀寫分離
這篇文章主要介紹了mysql主從基于docker和django實(shí)現(xiàn)讀寫分離,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-08-08mysql 5.7.12 winx64手動(dòng)安裝教程
這篇文章主要為大家詳細(xì)介紹了mysql 5.7.12 winx64手動(dòng)安裝配置方法圖文教程,感興趣的朋友可以參考一下2016-12-12