前言
上篇《VARCHAR(M) 到底占用多少個字節?|mysql系列(2)》分享了VARCHAR(M) 占用多少個字節,那VARCHAR 最大能存多少個字符呢?以及了解這些對我們平時的開發工作中有什么幫助呢?那我們就要了解下存儲引擎中是怎么來處理數據的。這里我們還是以InnoDB 為例。
InnoDB數據記錄的結構
在《執行sql 語句時發生了什么?|mysql 系列(1)》一文中講到,MySQL服務器上負責對表中數據的讀取和落盤(即寫入磁盤)工作是由存儲引擎 完成的。InnoDB是一個將表中的數據存儲到磁盤上的存儲引擎 。這也是mysql 持久化的保證。插入的數據記錄在磁盤上的存放方式被稱為行格式或者記錄格式。Mysql 目前有4種行格式:Redundant、Compact、Dynamic、Compressed.
其中:
-
Redundant 目前貌似很少使用了。
-
Version 5.6 默認使用 Compact
-
Version 5.7 默認使用Dynamic
可以用下面的語句來查看行格式。
我們以常用的Compact、Dynamic、Compressed 行格式為例。一條完整的記錄其實可以被分為記錄的額外信息和記錄的真實數據兩大部分 。Compact、Dynamic、Compressed行格式不同的地方在記錄的真實數據部分。我們尋求答案的地方在記錄的額外信息里面。
記錄的額外信息
記錄的額外信息包括:變長字段長度列表、NULL值列表和記錄頭信息。
變長字段長度列表: 比如VARCHAR(M)、VARBINARY(M)、各種TEXT類型,各種BLOB類型,把擁有這些數據類型的列稱為變長字段 ;
變長字段占用的存儲空間分為兩部分:
-
真正的數據內容
-
占用的字節數。
真實數據內容是就是存的具體的值。那么對於占用的字節數該怎么表示呢?
如果列中的字符串都比較短,也就是說內容占用的字節數比較小,用1個字節就可以表示,但是如果變長列的內容占用的字節數比較多,可能就需要用2個字節來表示。具體用1個還是2個字節來表示真實數據占用的字節數。
對於VARCHAR(M)來說:
-
表示能存儲最多M個字符(注意是字符不是字節),所以這個類型能表示的字符串最多占用的字節數就是M×L,其中L=設置字符集 Maxlen 的值。
-
假設它實際存儲的字符串占用的字節數是Z。
varchar(100) 的字段 name.
假設我們的字符集用一個字節表示一個字符。
設置name的值 為douglea.
那么name 的實際存儲的字節為7.
如果M×L <= 255,那么使用1個字節來表示真正字符串占用的字節數。
如果M×L > 255,則分為兩種情況:
-
如果Z <= 127,則用1個字節來表示真正字符串占用的字節數。
-
如果Z > 127,則用2個字節來表示真正字符串占用的字節數。
所以,如果最多有2個字節來表示真正字符串占用的字節數的話。2個字節能表示最大的數為:16個2進制位 也就是2的16次方= 65535。如果VARCHAR(M)類型的列使用的不是ascii字符集,那M的最大取值取決於該字符集表示一個字符最多需要的字節數。
舉個例子:
-
gbk字符集表示一個字符最多需要2個字節,那在該字符集下,M的最大取值就是32766(也就是:65532/2),也就是說最多能存儲32766個字符;
-
utf8字符集表示一個字符最多需要3個字節,那在該字符集下,M的最大取值就是21844,就是說最多能存儲21844(也就是:65532/3)個字符。
以上就是今天的分享,歡迎拍磚!