我理解的myisam引擎之二 MyISAM表(MYD)存儲格式

MyISAM存儲格式,也稱行格式(存儲的就是數據錶行數據)。衆所周知,MyISAM有三種類型的row_format行格式。fixed固定的行格式、dynamic動態行格式、compressed壓縮行格式。以下來逐一說明。

fixed固定行格式:當存儲殷勤爲myisam時,如果表不包括可變長度列(VARCHARVARBINARYBLOB, or TEXT),或者即使包括(VARCHARVARBINARY)列但是通過指定row_format=fixed。則表存儲格式即爲fixed的。例如:

mysql> create table t_fixed(id int,c1 char(10)) engine=myisam;
Query OK, 0 rows affected (0.22 sec)

mysql> create table t_fixed_1(id int,c1 char(10),c2 varchar(10)) engine=myisam row_format=fixed;
Query OK, 0 rows affected (0.19 sec)

mysql> create table t_fixed_2(id int,c1 char(10),c2 varchar(10),c3 blob) engine=myisam row_format=fixed;
Query OK, 0 rows affected (0.10 sec)

mysql> create table t_fixed_3(id int,c1 char(10),c2 varchar(10),c3 varbinary(10)) engine=myisam row_format=fixed;
Query OK, 0 rows affected (0.19 sec)

 

mysql> select TABLE_NAME,ENGINE,ROW_FORMAT,CREATE_OPTIONS  from information_schema.tables t where t.TABLE_NAME like 't_fixed%';
+------------+--------+------------+------------------+
| TABLE_NAME | ENGINE | ROW_FORMAT | CREATE_OPTIONS   |
+------------+--------+------------+------------------+
| t_fixed    | MyISAM | Fixed      |                  |
| t_fixed_1  | MyISAM | Fixed      | row_format=FIXED |
| t_fixed_2  | MyISAM | Dynamic    | row_format=FIXED |
| t_fixed_3  | MyISAM | Fixed      | row_format=FIXED |
+------------+--------+------------+------------------+
4 rows in set (0.00 sec)

這裏的t_fixed_2表,即使指定了row_format=fixed,但是因爲表中包括了blob列,最終的表的row_format爲dynamic。需要注意,這裏mysql並沒有給出警告或者錯誤。

fixed格式的表是最簡單的也是最安全的myisam表類型,同時因爲所有的行大小固定,要從表中獲取某一行極爲方便,只需要根據行號*行長度就可以找到行在數據文件中的偏移地址,因此是最快的磁盤結構。並且因爲沒有過多的輔助結構,一旦文件損壞,可以很容易的修復。對於char,varchar類型的字段,需要在真實字段值後面補空格;binary和varbinary類型的字段,則補0x00以對齊表定義中指定的字段長度。這裏有一點需要注意,mysql中的char,varchar指的是字符長度,不同的字符集需要的實際字節長度不同。fixed格式可以通過如下公式計算單行大小:

row length = 1 + (sum of column lengths) + (number of NULL columns + delete_flag + 7)/8 + (number of variable-length columns)

這裏來逐一解釋:

sum of column lengths:顯而易見,這個是表中所有列的長度。但注意的是要根據對應字符集確定實際的字節長度。

(number of NULL columns + delete_flag + 7)/8:number of NULL columns 對於沒有NOT NULL約束的列,每一列會使用一個二進制爲來表示對一個列的值是否爲NULL。這是爲了區分是補的空格還是實際值爲NULL。delete_flag標記此列是否已刪除。刪除的列的空間可以重用。對於一個大表,刪除大量數據後可能需要將數據文件所佔磁盤空間釋放回操作系統,可通過myisamchk工具或者optimize table來進行操作。+7是爲了與後面的/8後至少得到1.

1,number of variable-length columns尚沒有想明白是什麼原理。

dynamic動態行格式:通過create table的方式創建的myisam表,除了fixed格式的就是dynamic格式的。動態格式相比靜態格式就稍微複雜一些,沒行需要一個行頭來存儲行的實際長度,這個行頭通常是3字節。dynamic格式的行記錄在文件中是存在於稱爲frames的物理結構中的。一行記錄至少對應一個frame,設計frame這樣一個結構,是爲了重用已刪除的行佔用的空間。當向一個新創建的表中插入一條記錄,會從MYD文件空閒空間末尾分配一個大小等於行大小+輔助結構的frame。當從一個MYD中刪除一行記錄,則將對應的frame標記爲已刪除。當新的數據進來,空重用這個標記爲已刪除的frame,若行大小小於frame,則將此frame分裂爲兩部分,一部分用來存儲新插入的記錄,另一部分仍然標記爲已刪除;如果行大小大於此frame,則將行記錄的一部分存儲在此frame中,剩下的內容存儲在文件末尾中新分配的frame中。前面說,dynamic需要一個3字節的行頭來指示行長度,3字節能表示最大16M字節大小。因此frame的最大大小爲16M-4字節,最小爲20字節(包含3字節頭,加前後雙向鏈表指針)。當一行記錄超過16M大小,或者因爲update的緣故,導致行長度增長,都需要將多出來的行內容存儲到新分配的或者標記爲已刪除的frame結構中,並且根據需要存儲內容的大小和frame大小的不同,可能需要對frame進行分裂。https://dev.mysql.com/doc/internals/en/myisam-dynamic-data-file-layout.html 這種行存儲方式與oracle中的行鏈接和行遷移類似但是又有不同。官方文檔中列出了dynamic的一些特徵:

所有的string列,除過大小小於4字節的,都已dynamic方式存儲。

每一行都會前綴一個位圖,其中的二進制爲用來標識對應的列值是否爲空字符串或者0值。如果一列值爲空字符串或者0值,則在前綴中標記,並且不在磁盤上存儲。

每一個沒有NOT NULL約束的字段都需要一個bit來標識自己是否爲NULL。

相比fixed格式的表所使用的存儲空間大爲減少。

如果包含大量修改操作,容易產生碎片。需要通過optimize table或者myisamchk進行整理。

dynamic的行大小可通過如下公式計算:

3 + (number of columns + 7) / 8 + (number of char columns) + (packed size of numeric columns) + (length of strings) + (number of NULL columns + 7) / 8

其中:

3,表示3字節行頭。標識frame大小;

number of columns:位圖,標識對應列是否爲空字符串或者0值;

packed size of numeric columns:number數字類型的壓縮存儲格式,可參考myisam表索引文件對於number類型的壓縮方法。

length of strings:string列真實字段值總長度。

number of NULL columns:可能包含NULL值的字段數量,構成位圖。

 

compressed壓縮行格式:壓縮行格式只能通過myisampack工具產生,並且只讀。

壓縮表有以下特徵:

壓縮表只佔用很少的磁盤空間。這樣可以最大程度地減少磁盤使用,這在使用慢速磁盤(例如CD-ROM)時很有用。

每行分別進行壓縮,因此訪問開銷很小。根據表中最大的行,行的標題佔用一到三個字節。每列的壓縮方式不同。每列通常有不同的霍夫曼樹。一些壓縮類型是:

後綴空間壓縮。

前綴空間壓縮。

值爲零的數字使用一位存儲。

如果整數列中的值範圍較小,則使用最小的類型存儲該列。例如,如果BIGINT列(八個字節)的TINYINT所有值都在從-128到的範圍內,則可以將其存儲爲 列(一個字節) 127。

如果一列只有少量的可能值,則數據類型將轉換爲 ENUM。

列可以使用前述壓縮類型的任意組合。

可以用於固定長度或動態長度的行。

另外,因爲壓縮表只讀,因此不能進行修改操作。但是可以進行部分ddl操作,有效:drop table,truncate table。無效:add row

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章