现代数据库通常都支持CHAR与VARCHAR字符型字段类型,CHAR是用来保存定长字符,存储空间的大小为字段定义的长度,与实际字符长度无关,当输入的字符小于定义长度时最后会补上空格。VARCHAR是用来保留变长字符,在数据库中存储空间的大小是实际的字符长度,不会像CHAR同样补上空格,这样占用的空间更少。
从以上特色来看,VARCHAR比CHAR有明显的优点,所以大部份数据库设计时都应该采用VARCHAR类型。那为何还须要CHAR类型呢,我的认为有如下几个缘由:
一、为了跟之前版本的数据库进行一个兼容,由于好久之前数据库只支持CHAR类型,有些应用的业务逻辑也只是针对CHAR类型设计的,因此数据库软件也就一直保留CHAR类型。
二、CHAR类型是定长的,一些数据库能够在每条记录中不存储字段长度信息,这样能够节省部份空间,也能够方便作一些内存对齐提升性能,但我的认为这带来的性能提高很是微小,至少ORACLE数据库是没有意义的。
三、还有说法是有些数据常常修改,长度可能变化,会引发碎片,采用CHAR就不会产生碎片,这个说法比较多,但我认为既然长度会变化,那用VARCHAR更能节省内存与存储空间来提高性能,只要数据块预留的空间没有问题,采用VARCHAR性能更好。
对于ORACLE数据库,我找不到充足的理由来使用CHAR类型,并且CHAR还会带来讨厌的空格,有些文章说MYSQL的MYISAM存储引擎在和长度固定的状况下CHAR比VARCHAR好,这个没有测试过,不太了解。
因为VARCHAR是变长存储,那么不少人会有疑问,好比STATUS字段定义VARCHAR(10)与VARCHAR(1000)有什么区别,反正是变长的,存储空间都同样,免得之后要加长又要改变字段定义。 下面说一下个人理解:
一、字段长度是数据库一种约束,能够保证进入数据库的数据符合长度要求,定义合理的字段长度能够减小一部份非法数据进入,好比:咱们业务中STATUS只有‘NEW’,‘DELETE’,‘CLOSE’3种状态,使用VARCHAR(5)保存,这样能够有效的减小非法数据进入,定义合理的长度也可让人容易理解字段的用途,试想一下,若是你全部的字符字段长度都是VARCHAR(4000)会是什么样的状况。 sql
二、VARCHAR的字段长度虽然对数据存储没有太大影响,但对特定的数据库仍是有一些细微差异,好比MYSQL中定义的长度若是小于255,字段长度用1个字节表示,若是超过255,字段的长度将固定用2个字节表示。若是你的业务数据最大长度只有10,但定义长度为256则每条记录会多浪费了一个字节来存储长度。ORACLE没有这样的问题,它会根据每条记录字段的实际长度动态选择长度标识。 数据库
三、字段定义的长度对索引也有较大影响。ORACLE对索引长度仍是有必定限制,8i官方文档说明单条记录索引信息的长度不能超过数据块大小的40%,9i中是75%,实际上也差很少,具体能够见jametong的http://www.dbthink.com/?p=20这篇文档,里面有详细的测试结果。若是你的数据块大小是8K,那么索引字段的定义长度不能超过6398,好比,你要给表上2个VARCHAR(4000)字段建组合索引,建立时会直接报错。另外索引组织表及在线重建索引(由于中间会临时建立一个索引组织表)容许的索引信息长度更小,只能是数据块大小的40%,实际中8K的数据块大小,要使用在线重建索引,那定义的长度不能超过3215。从以上能够看出,数据块大小为8K时,设计字段时若是要定义为VARCHAR(4000),那这个字段就不能考虑创建索引,由于即便能建上,也不能作在线重定义操做,DBA要进行索引维护时只能中止应用,这将对系统的可用性产生较大影响。关于ORACLE索引长度限制测试的脚本以下: 服务器
五、关于字段长度对齐的问题,有些设计人员喜欢定义字段的长度为4或者8的倍数,如16,32,64,128之类的,理由是能够作到内存对齐,对于这个问题我没有深刻分析过,我的认为必要性不大,也没看到过这种优化能提高性能的案例。若是一个VARCHAR(1)定义为VARCHAR(4)反而浪费内存与存储,实际上我看到在ORACLE jdbc驱动中会将全部的字符类型数据保存在一个大的char[]中,把全部NUMBER与DATE类型放在另外一个char[]中,这样整合后都不清楚如何内存对齐了。
综上所述:VARCHAR类型字段长度不能随便定义,并非越大越好,仍是须要根据实际业务数据定义一个合适的长度。我我的对于一些能够彻底预估的长度就按实际长度定义,好比年月、状态、标记之类的信息。对于不肯定长度的业务数据如NAME、STYLE之类的信息定义一个合理值,如VARCHAR(20),VARCHAR(30) 之类 。对于描述性或备注性的信息,这些字段也肯定不会有索引,长度也不可预知,因此留更大的长度,避免之后常常进行长度调整,如VARCHAR(1024),或者直接VARCHAR2(4000) 。 并发