MyISAM和InnoDB的行格式ROW_FORMAT

MyISAM行存儲mysql

MyISAM3種行存儲格式:fixed/dynamic/compressedsql

其中fixed爲默認格式,只有當表不包含變長字段(varchar/varbinary/blob/text)時使用,該每行都是固定的,因此很容易獲取行在頁上的具體位置,存取效率比較高,可是佔用磁盤空間較多;oracle

dynamicspa

每行都有一個行頭部,包含bitmap,用以記錄那些列爲空(NULL列不算爲空)指針

相比於fixed,其有以下特性:rest

全部字符串列都是動態存儲的,除非長度小於4日誌

字符類型若長度爲0/數字類型爲0都會不佔用存儲空間,由bitmap標註,NULL值不包含在內;orm

若是要update行,其擴展後很容易致使行連接既而產生碎片,一旦crashlink丟失則比較難恢復,fixed模式update不會產生碎片;排序

 

compressed只能經過myisampack建立且爲只讀;索引

 

MyISAM的索引文件包含一個flag記錄基表是否正常關閉,若是mysqld啓動時指定了--myisam-recover-options,則在打開表時檢測並自動修復表

 

 

 

InnoDB行存儲

Innodb plugin新引入Barracuda梭子魚,其包含compressed/dynamic兩種行格式,而以前的compact/redundant統屬於antelope羚羊;

 

Barracuda VS antelope

innodb_file_format(動態)參數決定,目前可選值由AntelopeBarracuda,默認爲前者;要想要此參數生效,

由於共享表空間默認爲Antelope,所以要想使用Barracuda爲默認值,還必須先聲明innodb_file_per_table

Innodb_file_format用於控制行格式,全局變量可動態調整,5.5默認依舊是Antelope

 

下面只看antelope格式

 

Redundant行結構

字段長度偏移列表

記錄頭信息

1數據

2數據

….

 

行頭部爲字段長度偏移信息,包括變長和非變長的還包含了3個隱藏列:RowID(沒有主鍵時使用)/Transaction ID/Roll Point;compact只包含變長的,節約了空間;

冗餘行格式沒有NULL標誌位;對於redundant格式,varcharNull時不佔用空間,可是charNULL須要佔用空間,由於其沒有Null標誌位;

記錄頭信息佔用6個字節,比compact1字節;

對於定長char,若爲NULL依舊填充整個字段,而varcharNull時不佔用空間;

記錄頭信息,與compact相比,多了黑體字部分,缺失record_type

名稱

長度bit

功能

Deleted_flag

1

是否被刪除

Min_rec_flag

1

1則表示該記錄爲預先被定義的最小記錄

N_owned

4

該記錄擁有的總記錄數

Heap_no

13

索引中該行的排序記錄

N_fields

10

記錄中列數量

1byte_offs_flag

1

偏移量列表是1字節仍是2字節

Next_recorder

16

下一條記錄相對位置

()

1

未知

()

1

未知

 

Create table test(t1 varchar(10), t2 varchar(10), t3 char(10),t4 varchar(10)) charset=latin1 row_format=redundant;

--該表有3個變長列

Insert into test values(‘a’,’bb’,’bb’,’ccc’);

使用hexdump –C –v test.idb查看其二進制代碼

--長度偏移列表,

 

 

 

compact行格式

字段長度偏移列表

NULL標誌位

記錄頭信息

1數據

2數據

….

 

5.0引入

行頭存放該行內變長字段的length,當列小於255字節時佔用1個字節,大於255而小於65535時佔用2個字節;故varchar最大長度爲216次方-1

2個指示該行是否有NULL值,佔用1字節;NULL列不佔用數據存儲空間;

記錄頭信息:5個字節共計40bit,用於連接相鄰的記錄案的行級鎖

名稱

長度bit

功能

Deleted_flag

1

是否被刪除

Min_rec_flag

1

1則表示該記錄爲預先被定義的最小記錄

N_owned

4

該記錄擁有的總記錄數

Heap_no

13

索引中該行的排序記錄

Record_type

3

行類型 0=普通 1=B+節點指針

Next_recorder

16

下一條記錄相對位置

()

1

未知

()

1

未知

 

除此以外,每頁還有兩個隱含字段:

DB_TRX_ID6字節,記錄最近的一個事務標示符

DB_ROLL_ID7字節,指向回滾日誌記錄

--若沒有主鍵,則還會有DB_ROW_ID6字節,包含在clustered索引中

建立一個compact行格式的表

Create table test(t1 varchar(10), t2 varchar(10), t3 char(10),t4 varchar(10)) row_format=compact;

--該表有3個變長列

Insert into test values(‘a’,’bb’,’bb’,’ccc’);

使用hexdump –C –v test.idb查看其二進制代碼

第一行

03 02 01—變長字段長度列表(逆序),實際順序爲01 02 03,這也是t1,t2,t4的實際長度

00—Null標誌位,第一行沒有NULL

00 00 10 00 2c—記錄頭信息,5字節,後4個字節指向下一個記錄next_recorder

00 00 00 2b 68 00—6字節rowid,由於沒有主鍵

00 00 00 00 06 05 –事務ID6字節

80 00 00 00 32 01 10—回滾指針,7字節

61 –1

62 62 –2

62 62 20 20 20 20 20 20 20 20 –3char會填充餘下部分

63 63 63 –4

 

餘下的爲列數據,其中t3因爲採用固定長度,故會填充滿10個字節;

第二行

Insert into test values(‘d’,null,null,’fff’);

03 01--變長字段長度列表,逆序

06-- Null標誌位,有NULL值,轉換爲二進制00000110,表示第2/3列爲null

……

64—1數據

66 66 66—4數據,而第2/3列爲NULL不佔用存儲空間

注:對於redundant格式,varcharNull時一樣不佔用空間,可是charNULL須要佔用空間,由於其沒有Null標誌位

行溢出

Innodb表爲IOT,採用了B+數類型,故每一個頁面至少要存儲2行數據,若是行過大則會產生行溢出;

理論上mysqlvarchar可存儲65525字節,強於oracle4000,但對於InnoDB其實際上限爲65532,且該值爲表全部varchar列長度總和;對於utf8字符集,一個字符佔3個字節,則其上限又縮小爲1/3

若是強行建立varchar(65535)的字段,在sql_mode不爲restricted的狀況下,其會被隱式轉換爲mediumtext

 

不管是varchar仍是blob/text,只要保證一個16k的頁面能容下2行數據,應該不會行溢出;

而一旦行溢出,字段前768字節依舊存放於當前頁面,數據通常使用B-tree Node頁,而溢出的行存放於Uncompress Blob頁;

 

barracuda採用了徹底行溢出,即只保留字段的前20字節;

相關文章
相關標籤/搜索