MySQL数据类型varchar详解
1、varchar(N)的逻辑意义
从MySQL4.1开始,varchar (N)中的N指的是该字段最多能存储多少个字符(characters),不是字节数。
不管是⼀个中英⽂字符或者数字、或者⼀个汉字,都当做⼀个字符。在4.1之前,N表⽰的是最⼤存储的字节数(bytes)。
2、varchar(N)到底能存多长的数据
在mysql reference manual上,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。
代码如下:
CREATE TABLE `vchar1` (  `name` VARCHAR(65533)  NOT  NULL ) ENGINE=InnoDB DEFAULT
CHARSET=latin1;
CREATE TABLE `vchar2` (  `name` VARCHAR(65533)  NOT  NULL ) ENGINE=MyISAM DEFAULT
CHARSET=latin1;
如果数据表只有⼀个varchar字段且该字段NOT NULL,那么该varchar字段的最⼤长度为65533个字节,即65535-2=65533bytes。
代码如下:
CREATE TABLE `vchar3` (  `name` VARCHAR(65532)  DEFAULT  NULL ) ENGINE=InnoDB
DEFAULT CHARSET=latin1;
CREATE TABLE `vchar4` (  `name` VARCHAR(65532)  DEFAULT  NULL ) ENGINE=MyISAM
DEFAULT CHARSET=latin1;
来个略微复杂点的表结构,->
代码如下:
CREATE TABLE `tv` (
`a` VARCHAR(100) DEFAULT NULL,
`b` VARCHAR(100) DEFAULT NULL,
`c` VARCHAR(100) DEFAULT NULL,
`d` VARCHAR(100) DEFAULT NULL,
`e` VARCHAR(100) DEFAULT NULL,
`f` VARCHAR(100) DEFAULT NULL,
`g` VARCHAR(100) DEFAULT NULL,
`h` VARCHAR(100) DEFAULT NULL,
`i` VARCHAR(N) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
`i` varchar(N) DEFAULT NULL中N最⼤值可以为多少?
这样计算:已知确定的字段长度为100*8  bytes,8个varchar(100)字段总共需要变长字段表⽰字节为1*8=8 bytes。每个NULL字段⽤1bit标识,9个字段都是default null,那么需要⽤(9+7)/8bit = 2 bytes存储NULL标识位。65535-100*8-1*8-2 = 64725 > 256, 那么字段i的最⼤长度为64725  - 2 =64723 bytes,即
N=64723 。
varchar到底能存多少个字符?这与使⽤的字符集相关,latin1、gbk、utf8编码存放⼀个字符分别需要占1、2、3个字节。mysql创建表数据类型
3、varchar物理存储
在物理存储上,varchar使⽤1到2个额外的字节表⽰实际存储的字符串长度(bytes)。如果列的最⼤长度⼩于256个字节,⽤⼀个字节表⽰(标识)。如果最⼤长度⼤于等于256,使⽤两个字节。
当选择的字符集为latin1,⼀个字符占⽤⼀个byte
varchar(255)存储⼀个字符,⼀共使⽤2个bytes物理空间存储数据实际数据长度和数据值。
varchar(256)存储⼀个字符,使⽤2 bytes表⽰实际数据长度,⼀共需要3 bytes物理存储空间。
varchar对于不同的RDBMS引擎,有不通的物理存储⽅式,虽然有统⼀的逻辑意义。对于mysql的不同存储引擎,其实现⽅法与数据的物理存放⽅式也不同。4、InnoDB中的varchar
InnoDB中varchar的物理存储⽅式与InnoDB使⽤的innodb_file_format有关。早期的innodb_file_forma使⽤的Antelope⽂件格式,⽀持redundant和compact两种row_format。从5.5开始或者InnoDB1.1,可以使⽤⼀种新的file format,Barracuda。Barracuda兼容Redundant,另外还⽀持dynamic和compressed两种
row_format.
当innodb_file_format=Antelope,ROW_FORMAT=REDUNDANT 或者COMPACT。
innodb的聚集索引(cluster index)仅仅存储varchar、text、blob字段的前768个字节,多余的字节存储在⼀个独⽴的overflow page中,这个列也被称作off-page。768个字节前缀后⾯紧跟着20字节指针,指向overflow pages的位置。
另外,在innodb_file_format=Antelope情况下,InnoDB中最多能存储10个⼤字段(需要使⽤off-page存储)。innodbd的默认page size为16KB,InnoDB单⾏的长度不能超过16k/2=8k个字节,(768+20)*10 < 8k。
当innodb_file_format=Barracuda, ROW_FORMAT=DYNAMIC 或者 COMPRESSED
innodb中所有的varchar、text、blob字段数据是否完全off-page存储,根据该字段的长度和整⾏的总长度⽽定。对off-page存储的列,cluster index中仅仅存储20字节的指针,指向实际的overflow page存储位置。如果单⾏的长度太⼤⽽不能完全适配cluster index page,innodb将会选择最长的列作为off-page存储,直到⾏的长度能够适配cluster index page。
5、MyISAM中的varchar
对于MyISAM引擎,varchar字段所有数据存储在数据⾏内(in-line)。myisam表的row_format也影响到varchar的物理存储⾏为。
MyISAM的row_format可以通过create或者alter sql语句设为fixed和dynamic。另外可以通过myisampack⽣成row_format=compresse的存储格式。
当myisam表中不存在text或者blob类型的字段,那么可以把row_format设置为fixed(也可以为dynamic),否则只能为dynamic。
当表中存在varchar字段的时候,row_format可以设定为fixed或者dynamic。使⽤row_format=fixed存储varchar字段数据,浪费存储空间,varchar此时会定长存储。row_format为fixed和dynamic,varchar的物理实现⽅式也不同(可以查看源代码⽂件field.h和),因⽽myisam的row_format在fixed和dynamic之间发⽣转换的时候,varchar字段的物理存储⽅式也将会发⽣变化。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。