http://www.chinaz.com/program/2011/0503/176896.shtmlhtml
在数据库中,字符型的数据是最多的,能够占到整个数据库的80%以上。为此正确处理字符型的数据,对于提升数据库的性能有很大的做用。在字符型数据中,用的最多的就是Char与Varchar两种类型。前面的是固定长度,然后面的是可变长度。如今咱们须要考虑的是,在什么状况下使用Char字符型数据,什么状况下采用Varchar字符型数据。在这部份内容中,我就跟你们来探讨一下这个话题。数据库
1、VARCHAR与CHAR字符型数据的差别性能
在MySQL数据库中,用的最多的字符型数据类型就是Varchar和Char.。这两种数据类型虽然都是用来存放字符型数据,可是不管从结构仍是从数据的保存方式来看,二者相差很大。并且其具体的实现方式,还依赖与存储引擎。我这里就以你们最经常使用的MYISAM存储引擎为例,谈谈这两种数据类型的差别。在后续建议中,也是针对这种存储类型而言的。htm
这里首先须要明白的一点是,这两种数据类型,不管采用哪种存储引发,系统存储数据的方式都是不一样的。正是由于如此,咱们才有必要研究二者的不一样。而后在合适的状况下,采用恰当的方式。了解这一点以后,咱们再来看后续的内容。排序
Varchar每每用来保存可变长度的字符串。简单的说,咱们只是给其固定了一个最大值,而后系统会根据实际存储的数据量来分配合适的存储空间。为此相比CHAR字符数据而言,其可以比固定长度类型占用更少的存储空间。不过在实际工做中,因为某系特殊的缘由,会在这里设置例外。如管理员能够根据须要指定ROW_FORMAT=FIXED选项。利用这个选项来建立MyISAM表的话,系统将会为每一行使用固定长度的空间。此时会形成存储空间的损耗。一般状况下,VARCHAR数据类型可以节约磁盘空间,为此每每认为其可以提高数据库的性能。不过这里须要注意的是,这每每是一把双刃剑。其在提高性能的同时,每每也会产生一些反作用。如由于其长度是可变的,为此在数据进行更新时可能会致使一些额外的工做。如在更改前,其字符长度是10位(Varchar规定的最长字符数假设是50位),此时系统就只给其分配10个存储的位置(假设不考虑系统自身的开销)。更改后,其数据量达到了20位。因为没有超过最大50位的限制,为此数据库仍是容许其存储的。只是其原先的存储位置已经没法知足其存储的需求。此时系统就须要进行额外的操做。如根据存储引擎不一样,有的会采用拆分机制,而有的则会采用分页机制。内存
CHAR数据类型与VARCHAR数据类型不一样,其采用的是固定长度的存储方式。简单的说,就是系统总为其分配最大的存储空间。当数据保存时,即便其没有达到最大的长度,系统也会为其分配这么多的存储空间。显然,这种存储方式会形成磁盘空间的浪费。这里笔者须要提醒的一点是,当字符位数不足时,系统并不会采用空格来填充。相反,若是在保存CHAR值的时候,若是其后面有空值,系统还会自动过滤其空格。而在进行数据比较时,系统又会将空格填充到字符串的末尾。字符串
显然,VARCHAR与CHAR两种字符型数据类型相比,最大的差别就是前者是可变长度,然后者则是固定长度。在存储时,前者会根据实际存储的数据来分配最终的存储空间。然后者则无论实际存储数据的长度,都是根据CHAR规定的长度来分配存储空间。这是否意味着CHAR的数据类型劣于VARCHAR呢?其实否则。不然的话,就没有必要存在CHAR字符类型了。虽然VARCHAR数据类型能够节省存储空间,提升数据处理的效率。可是其可变长度带来的一些负面效应,有时候会抵消其带来的优点。为此在某些状况下,仍是须要使用Char数据类型。get
2、项目建议class
根据上面的分析,咱们知道VARCHAR数据类型是一把双刃剑,其在带来性能提高的同时,也可能会存在着一些额外的消耗。咱们在评估究竟是使用VARCHAR数据类型仍是采用CHAR数据类型时,就须要进行均衡。在实际项目中,咱们会考量以下状况。效率
一是根据字符的长度来判断。如某个字段,像人的名字,其最长的长度也是有限的。如咱们给其分配18个字符长度便可。此时虽然每一个人的名字长度有可能不一样,可是即便为其分配了固定长度的字符类型,即18个字符长度,最后浪费的空间也不是很大。而若是采用NVARCHAR数据类型时,万一之后须要更名,而原先的存储空间不足用来容纳新的值,反而会形成一些额外的工做。在这种状况下,进行均衡时,会认为采用CHAR固定长度的数据类型更好。在实际项目中,若是某个字段的字符长度比较短此时通常是采用固定字符长度。
二是考虑其长度的是否相近。若是某个字段其长度虽然比较长,可是其长度老是近似的,如通常在90个到100个字符之间,甚至是相同的长度。此时比较适合采用CHAR字符类型。比较典型的应用就是MD5哈希值。当利用MD5哈希值来存储用户密码时,就很是使用采用CHAR字符类型。由于其长度是相同的。另外,像用来存储用户的身份证号码等等,通常也建议使用CHAR类型的数据。
另外请你们考虑一个问题,CHAR(1)与VARCHAR(1)两这个定义,会有什么区别呢?虽然这两个都只可以用来保存单个的字符,可是VARCHAR要比CHAR多占用一个存储位置。这主要是由于使用VARCHAR数据类型时,会多用1个字节用来存储长度信息。这个管理上的开销CHAR字符类型是没有的。
三是从碎片角度进行考虑。使用CHAR字符型时,因为存储空间都是一次性分配的。为此某个字段的内容,其都是存储在一块儿的。单从这个角度来说,其不存在碎片的困扰。而可变长度的字符数据类型,其存储的长度是可变的。当其更改先后数据长度不一致时,就不可避免的会出现碎片的问题。故使用可变长度的字符型数据时,数据库管理员要时不时的对碎片进行整理。如执行数据库导出导入做业,来消除碎片。
四是即便使用Varchar数据类型,也不可以太过于慷慨。这是什么意思呢?如如今用户须要存储一个地址信息。根据评估,只要使用100个字符就能够了。可是有些数据库管理员会认为,反正Varchar数据类型是根据实际的须要来分配长度的。还不如给其大一点的呢。为此他们可能会为这个字段一次性分配200个字符的存储空间。这VARCHAR(100)与VARCHAR(200)真的相同吗?结果是否认的。虽然他们用来存储90个字符的数据,其存储空间相同。可是对于内存的消耗是不一样的。对于VARCHAR数据类型来讲,硬盘上的存储空间虽然都是根据实际字符长度来分配存储空间的,可是对于内存来讲,则不是。其时使用固定大小的内存块来保存值。简单的说,就是使用字符类型中定义的长度,即200个字符空间。显然,这对于排序或者临时表(这些内容都须要经过内存来实现)做业会产生比较大的不利影响。因此若是某些字段会涉及到文件排序或者基于磁盘的临时表时,分配VARCHAR数据类型时仍然不可以太过于慷慨。仍是要评估实际须要的长度,而后选择一个最长的字段来设置字符长度。若是为了考虑冗余,能够留10%左右的字符长度。千万不能认为其为根据实际长度来分配存储空间,而随意的分配长度,或者说干脆使用最大的字符长度。