首页 > 数据库技术 > 详细

MySQL之varchar

时间:2015-10-23 15:56:23      阅读:459      评论:0      收藏:0      [点我收藏+]

MySQL之varchar

0.前言


 关于MySQL中varchar长度的定义,人人都有自己的见解,不同的人凑在一起一定会争论。但是这也是每一个人的痛点,没有人能够说清楚为什么这么设置varchar的长度。

或许,这篇wiki里我也没有说清楚,但是至少可以提供某种角度的借鉴。更或许,这篇wiki中会有一些纰漏,让争论继续下去。

但是,我的初衷并不在此,而是仅仅让自己弄明白某些东西,起码能多学到一些以前未了解的。也可以直接认为,我只是为了找一些充足的证据,说服自己,仅仅是说服自己,而不是说服其他人。

不管你们信不信,反正我自己是信了。

1.研究MySQL的varchar列类型的背景


1.MySQL5.x

2.InnoDB

 2.varchar之争


对于varchar的争论,目前总结来看,主要有三种看法:(注:以下讨论仅仅在非严格模式下的MySQL)

第一种:技术分享

varchar(3)表示varchar能存储3个字节,存储如下表:

要插入的字符实际存入的字符占用长度
ab ab 2字节
abc abc 3字节
abcd abc 3字节

 

 第二种:技术分享

varchar(3)不能表示varchar能存储3个字节,因为按照MySQL官方文档的定义,会有一个字节用来存储长度,所以3个字节只能存两个字母字符。

要插入的字符实际存入的字符占用长度
ab ab 3字节
abc ab 3字节
abcd ab 3字节 

 这种说法很有道理,因为官方文档都说了,会有一个字节用来存储长度。这里把文档的原话翻译一下引入进来:

VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节)。

第三种:技术分享

varchar(3)表示varchar能够存储3个字符,注意这里是字符,不是字节。也就是说无论汉字,还是字母等,都是一个字符。关于汉字占的字节数我会在下面介绍。

要插入的字符实际存入的字符占用长度
ab ab 3字节
abc abc 4字节
abcd abc 4字节
中国人 中国人 10字节

这种说法是对的。 当然,这里有个前提,即编码格式是UTF-8。不对,是UTF8。这是需要注意的点是中间的连字符:数据库中为UTF8 ,在程序中是UTF-8.

MySQL字符集

MySQL字符集的解释,http://doc.mysql.cn/mysql5/refman-5.1-zh.html-chapter/charset.html

MySQL支持的字符集有Unicode字符集,西欧字符集,中欧字符集,南欧与中东字符集,波罗的海字符集,西里尔字符集和亚洲字符集。

这么多我也是看醉了。最常用的是Unicode字符集,而这种字符集里又分两种,一种ucs2,另一种为utf8

UTF8字符集的思想,是不同Unicode字符采用变长字节序列编码:

  • 基本拉丁字母,数字和标点使用一个字节
  • 大多数的欧洲和中东手写字母适合两个字节序列
  • 韩语,中文和日本象形文字使用三个字节序列

结论:

第一种说法是错误的。

第二种说法在MySQL4.X是正确的,显然现在肯定不对。

第三种说法在MySQL5.x是正确的。

 

3.MySQL存储

上一章讨论的结果,从官方文档中证实第三种说法是正确的。

但是如果我要存50个字符,就定义成varchar(50),如果要存500个字符,就定义成varchar(500)吗?

看看以前的老代码,很多都不是这样,他们都定义成varchar(63),varchar(127),varchar(255)这样。

在这里,我认为他们是受了传统的MySQL4.x的影响。

至于为什么我会在“最大50个字符用varchar(50)来生命”存在疑问,是源于Hadoop的存储方式。

疑问的由来------Hadoop之block

Hadoop是广而人之的分布式框架,基于MapReduce。

简单的Hadoop可以看成是一个主机,多个从机,主机用来分发任务等,从机用于存储和计算等。很明显当数据到来的时候,这个数据的容量超过了单个从机的容量,主机会把一个非常大的文件打成若干个小块,分布式地存储到从机上。此时,最小的存储单位就叫做block,默认的是64M。当一个65M的文件进来,可以粗略的认为,就会分割成64M和1M(当然为了保证数据的完整性,不可能分为精确的64M)。这样,65M的文件就会占用两个block的空间,128M。就会存在空间的浪费。

MySQL的InnoDB存储结构

如Hadoop的存储一般,MySQL会不会出现类似的情况?它又对varchar的长度声明有何影响?

我觉得MySQL会出现类似的情况。查了一下资料,果然。

MySQL中InnoDB的数据存储结构从大到小,分为:Tablespace,segment,extend,page(block),row。

唉,page竟然有个别名也叫block。果然我的猜想应该是有点道理的。

来个图吧,从网上找的

技术分享

每个table对应一个tablespace,在tablespace中,index/数据/transaction信息又各自存放于不同的segment。

每个segment又分64个连续page,每个page固定大小16K。

4.结论

分析了存储结构之后,我们基本上就可以得出结论了。

存储引擎是按页读取的,也就是说,内容最好在一页上。但是page的子节点是row和索引,而且对于数据存储量,我们是无法控制的。

所以一切就OUT OF CONTROLL了,以上的疑问没有什么卵用。

最终的结论就是:如果你的一列需要50个字符,就定义varchar(50),如果考虑扩展性,就可以定得再高一些。不必刻意去用63,127和255这样的数字来定义长度。

5.提醒和声明

以上研究和结论,只属于个人言论和看法。仅供借鉴。谢谢。

参考5.1官方文档

http://doc.mysql.cn/mysql5/refman-5.1-zh.html-chapter/

MySQL之varchar

原文:http://www.cnblogs.com/AaronCui/p/4904487.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!