在MySQL中,char和varchar可能是我们最常使用字符串类型。那么到底varchar和varchar有什么不同?我们什么时候使用char,什么时候使用varchar呢?
char
cahr是定长的,插入数据不足规定长度的,右边补空格,当然查询出来的数据也会有空格,插入数据超过规定长度的,会报错,因为mysql并不会自动截短字符串。因为char是定长的,所以查询效率比varchar高,但是对于分配的长度不能充分利用的情况下会造成一定的空间浪费
varchar
varchar是不定长的,varchar类型的列是不定长的,在5.0版本以后最大长度为65536个字节(2^16),但是这个长度只是系统长度,并不意味着你真的可以完全利用65536字节来存储数据,因为varchar是不定长的,所以需要前两个字节标记字段的实际长度,结尾还要用一个字节表示结束,者可以用u盘来说明,买一个256G的u盘,但是实际并不足256G,因为系统也要占用一部分。
需要注意的是65535只是字节个数,而且是理论字节个数,在减去头尾系统占用字节后,只剩下65533可用字节。那么我们建表的时候,能不能直接写varchar(65533)呢?当然是不行的,在4.0版本之后,varchar后面的小括号里就不再是字节长度了,而是字符长度
为什么char类型查询效率高
这是由他们在磁盘上存放的不同形式决定的,我们先来看一个图:
我们可以看到char类型在存放数据的时候,中间是没有间隔的,数据本身是有空格的,但是数据段之间没有间隔,因为我们在创建列的时候已经告诉MySQL列的长度了,MySQL在查询数据的时候,只需要按部就班寻找就行了,不需要在中途计算这个数据段的长度。
但是varchar类型的存放就不同了,在每个数据段开头,都要有一段空间(1~2个字节)存放数据段的长度,在数据段的结尾还有一段空间(1个字节)标记此字段的节数。MySQL在读取一个数据段的时候,首先要读开头,比如读到了3,说明数据段的长度是3,之后就不多不少,只读3个字节。所以MySQL在遍历数据的时候,磁针要比char类型的列多读很多次磁盘来获取字段的真实长度,这就是为什么varchar比char查询效率低的原因了。
应用
我们可以用varchar存放不定长的数据,比如人的名字,或者一篇博客的文章。可以用char存放定长的数据,比如身份证号和手机号,我们把一个列定义为mobile varchar(11),*的手机号最长,达到11位,香港是8位,瑞士是10位,所以定义成11位完全够用,可以存放各国的手机号了。
额外说明下,我们在定义字段最大长度时应该按需分配,提前做好预估。特别是对于VARCHAR字段,有人认为反正VARCHAR数据类型是根据实际的需要来分配长度的,还不如给大一点呢。但事实不是这样的,比如现在需要存储一个地址信息,根据评估,只要使用100个字符就可以了,我们可以使用VARCHAR(100)或VARCHAR(200)来存储,虽然它们用来存储90个字符的数据,其存储空间相同,但是对于内存的消耗是不同的。更长的列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内部值,尤其是使用内存临时表进行排列或者操作时会特别糟糕。所以我们在分配VARCHAR数据类型时仍然不能够太过于慷慨。还是要评估实际需要的长度,然后选择一个最长的字段来设置字符长度。如果为了考虑冗余,可以留10%左右的字符长度。千万不能认为VARCHAR是根据实际长度来分配存储空间,而随意的分配长度,或者说干脆使用最大的字符长度。