Mysql字段長度限制你真的瞭解嗎?

   一行中可以容納多少字段長度?每個字段擁有長度又可以是多少?是否數據類型的限制長度固定不變?帶着這幾個問題,我們開始進行一系列研究。

一、行容納的字段長度

   衆所周知,記錄是以行的形式進行保存的,Mysql5.1以後,行的保存格式默認爲Compact格式。行記錄Compact格式爲:



變長字段NULL標誌位記錄頭信息列1數據列2數據列3數據...


   第一個變長字段是記錄這行的總字段長度,如果行記錄的字段總長小於255字節,變長字段就佔一個字節(一個字節有8位,8位的二進制最多能表示到255)。當大於255時,變長字段的長度就是兩個字節。Mysql規定變成字段不超過兩個字節,就意味着行的段總長最多不能超過65535個字節(兩個字節有16位,16位最多能表示65535)

mysql> create table test_limit (idvarchar(65531),name char(1) )charset=latin1;
Query OK, 0 rows affected (0.00 sec)

可以看出來65531+1=65532<=65532(65535-1-2, -1是因爲一個字節不存數據,-2是因爲兩個字節varchar的長度)


mysql> create table test_limit  (id varchar(65531),name char(2))charset=latin1;
ERROR 1118 (42000): Row size too large. Themaximum row size for the used table type, not counting BLOBs, is 65535. Thisincludes storage overhead, check the manual. You have to change some columns toTEXT or BLOBs

                     65533>65532所以不被允許


二、每個字段容納長度

   每個字段長度首先要符合字符類型限制的長度,然後再看是否符合行的段總長

   值得注意的是,對於varchar的最大長度來說要根據字符集而變化

mysql> create table varchar_var (idvarchar(65531)) charset=utf8;
ERROR 1074 (42000): Column length too bigfor column 'id' (max = 21845); use BLOB or TEXT instead

Utf8中一個字符相當於3個字節,所以需要65 536/3≈21845

mysql> create table varchar_var (idvarchar(41843),name int )charset=gbk;
ERROR 1074 (42000): Column length too bigfor column 'id' (max = 32767); use BLOB or TEXT instead

Gbk中一個字符相當於2個字節,65 536/2≈32767

mysql> create table varchar_var (idvarchar(75536) )charset=latin1;
ERROR 1074 (42000): Column length too bigfor column 'id' (max = 65535); use BLOB or TEXT instead

latin1是一個字符相當於一個字節

mysql> create table extend_char (namechar(1));
 
mysql> insert into extend_char values ('的我');
ERROR 1406 (22001): Data too long forcolumn 'name' at row 1

可見,char(1)只保存一個字符,在存儲中utf8字符集的佔3個字節

  int固定佔的是4個字節,4個8位二進制所以表示範圍爲-2 147 483 648~2147 483 647。

既然是固定佔4個字節,那麼Int(1),int(2)在存儲空間上就差別不大。唯一的區別在於當你設置zerofill才能顯現,他會用0補足顯示寬度:

mysql> create table extend_int_zero(name int zerofill) charset=latin1;
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into extend_int_zerovalues (1);
Query OK, 1 row affected (0.01 sec)
 
mysql> select * from extend_int_zero;
+------------+
| name      |
+------------+
| 0000000001 |
+------------+

當int不寫顯示寬度時默認爲int(11)


三、實戰分析

mysql> create table row_for (idvarchar(21843),name int );

這是在utf8字符集下的,你看看這句是否會執行成功呢?

 

21843*3=65529##utf8中一個字符等於三個字集

65529+4=65533##int佔4個字節

65533+1+2=65535##前面提及的,一個字節不存數據,兩個字節存放長度

所以這一行的總字段長度65535,,因爲65535正好超過了行的段規定長度所以不被允許

 

如果將varchar類型下調一個字符,那就正確了

mysql> create table row_d (idvarchar(21842),name int );
Query OK, 0 rows affected (0.02 sec)


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