1、char
char最大長度是255字符,注意是字符數和字符集沒關系。
1)可以有默認值,
2)尾部有空格會被截斷
3)不管漢字、英文,還是其他編碼,都可以存255字符
2、varchar
1)varchar最多能存儲65535個字節的數據,varchar 的最大長度受限於最大行長度(max row size,65535bytes),65535並不是一個很精確的上限,可以繼續縮小這個上限
65535個字節包括所有字段的長度,變長字段的長度標識(每個變長字段額外使用1或者2個字節記錄實際數據長度)、NULL標識位的累計
NULL標識位,如果varchar字段定義中帶有default null允許列空,則需要需要1bit來標識,每8個bits的標識組成一個字段
一張表中存在N個varchar字段,那么需要(N+7)/8 (取整)bytes存儲所有的NULL標識位
如果數據表只有一個varchar字段且該字段DEFAULT NULL,那么該varchar字段的最大長度為65532個字節,即65535-2-1=65532 bytes
在物理存儲上,varchar使用1到2個額外的字節表示實際存儲的字符串長度(bytes)。如果列的最大長度小於256個字節,用一個字節表示(標識)。如果最大長度大於等於256,使用兩個字節。當選擇的字符集為latin1,一個字符占用一個bytevarchar(255)存儲一個字符,一共使用2個bytes物理空間存儲數據實際數據長度和數據值。varchar(256)存儲一個字符,使用2 bytes表示實際數據長度,一共需要3 bytes物理存儲空間。
2)可以有默認值
3)尾部有空格不會截斷
create table test(name varchar(65533) not null)engine=innodb DEFAULT CHARSET=latin1
使用latin1編碼的時候
mysql> drop table if exists test;create table test(name varchar(65533) not null)engine=innodb DEFAULT CHARSET=latin1; Query OK, 0 rows affected (0.04 sec) Query OK, 0 rows affected (0.18 sec) mysql> drop table if exists test;create table test(name varchar(65534) not null)engine=innodb DEFAULT CHARSET=latin1; Query OK, 0 rows affected (0.05 sec) ERROR 1118 (42000): Row size too large. The maximum row size for the used table type,\ not counting BLOBs, is 65535. This includes storage overhead, check the manual. \ You have to change some columns to TEXT or BLOBs mysql> drop table if exists test;create table test(name varchar(65533) null)engine=innodb DEFAULT CHARSET=latin1; Query OK, 0 rows affected, 1 warning (0.00 sec) ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, \ not counting BLOBs, is 65535. This includes storage overhead, check the manual. \ You have to change some columns to TEXT or BLOBs mysql> drop table if exists test;create table test(name varchar(65532) null)engine=innodb DEFAULT CHARSET=latin1; Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.04 sec)
可以看出最大可存儲的為65533字節,not null 的時候,其中兩個字節記錄長度
使用utf8編碼的時候
mysql> drop table if exists test;create table test(name varchar(65533) not null)engine=innodb DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.06 sec) ERROR 1074 (42000): Column length too big for column 'name' (max = 21845); use BLOB or TEXT instead mysql> drop table if exists test;create table test(name varchar(21845) not null)engine=innodb DEFAULT CHARSET=utf8; Query OK, 0 rows affected, 1 warning (0.00 sec) ERROR 1118 (42000): Row size too large. The maximum row size for the used table type,\ not counting BLOBs, is 65535. This includes storage overhead, check the manual. \ You have to change some columns to TEXT or BLOBs mysql> drop table if exists test;create table test(name varchar(21844) not null)engine=innodb DEFAULT CHARSET=utf8; Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.24 sec)
可以看出最大值為(65535-2)/3=21844,(65535-2-1)/3=21844
InnoDB中的varchar
InnoDB中varchar的物理存儲方式與InnoDB使用的innodb_file_format有關
1)早期的innodb_file_forma使用的Antelope文件格式,支持redundant和 compact兩種row_format
2)從5.5開始或者InnoDB1.1,可以使用一種新的file format,Barracuda,Barracuda兼容Redundant,另外還支持dynamic和compressed兩種row_format
當innodb_file_format=Antelope,ROW_FORMAT=REDUNDANT或者COMPACT時
1)innodb 的聚集索引(cluster index)僅僅存儲varchar、text、blob字段的前768個字節,多余的字節存儲在一個獨立的overflow page中,這個列也被稱作off-page
2)768個字節前綴后面緊跟着20字節指針,指向overflow pages的位置
3)在 innodb_file_format=Antelope情況下,InnoDB中最多能存儲10個大字段(需要使用off-page存儲)
4)innodbd的默認page size為16KB,InnoDB單行的長度不能超過16k/2=8k個字節,(768+20)*10 < 8k
當innodb_file_format=Barracuda, ROW_FORMAT=DYNAMIC 或者 COMPRESSED
1)innodb 中所有的varchar、text、blob字段數據是否完全off-page存儲,根據該字段的長度和整行的總長度而定
2)對off-page存儲的列,cluster index中僅僅存儲20字節的指針,指向實際的overflow page存儲位置
3)如果單行的長度太大而不能完全適配cluster index page,innodb將會選擇最長的列作為off-page存儲,直到行的長度能夠適配cluster index page
MyISAM中的varchar
對於MyISAM引擎,varchar字段所有數據存儲在數據行內(in-line),myisam表的row_format也影響到varchar的物理存儲行為
1)MyISAM的row_format可以通過create或者alter sql語句設為fixed和dynamic,另外可以通過myisampack生成row_format=compresse的存儲格式
2)當myisam表中不存在text或者blob類型的字段,那么可以把row_format設置為fixed(也可以為dynamic),否則只能為dynamic
3)當表中存在varchar字段的時候,row_format可以設定為fixed或者dynamic,使用row_format=fixed存儲 varchar字段數據,浪費存儲空間,varchar此時會定長存儲
4)row_format為fixed和dynamic,varchar的物理實現方式也不同(可以查看源代碼文件field.h和field.cc
5)因而myisam的row_format在fixed和dynamic之間發生轉換的時候,varchar字段的物理存儲方式也將會發生變化
text
1)text和varchar基本相同
2)text會忽略指定的大小這和varchar有所不同,text不能有默認值
3)尾部有空格不會被截斷
4)text使用額 外的2個字節來存儲數據的大小,varchar根據存儲數據的大小選擇用幾個字節來存儲
5)text的65535字節全部用來存儲數據,varchar則會 占用1-3個字節去存儲數據大小
效率來說基本是char>varchar>text,但是如果使用的是Innodb引擎的話,推薦使用varchar代替