varchar和char是两种最主要的字符串类型。不幸的是,很难精确地解释这些值是怎么储存在磁盘和内存中的,因为这根存储引擎的具体实现有关。下面的描述假设使用的存储引擎是InnoDB或者MyISAM。如果使用的不是这两种存储引擎,请参考所使用的存储引擎的文档。

  先看看varchar和char值通常在磁盘上怎么存储的。请注意,存储引擎存储char或者varchar值的方式在内存中和磁盘上可能不一样,所以MySQL服务器从存储引擎读出的值可能需要转换成另一种存储格式。下面是关于两种类型的一些比较。

varchar

  varchar类型用于存储可变长度字符串,是最常见的字符串数据类型。它比定长类型更节省空间,因为它仅使用必要的空间(例如,越短的字符串使用越少的空间)。有一种情况例外,MySQL表使用ROW_FROMAT=FIXED创建的话,每一行都会使用定长存储,这会很浪费空间。

  varchar需要使用1或者2个额外字节记录字符串的长度:如果列的最大长度小于或者等于255字节,则使用1个字节表示,否则使用2个字节。假设采用latin1字符集,一个varchar(10)的列需要2个字节存储长度信息。

   varchar节省了存储空间,所以针对性能也有帮助。但是由于长度是变长的,在update时可能使行变得比原来更长,这就导致需要做些额外的工作。但是如果一个行占用的空间增长,并且在页内没有更多的空间可以存储,在这种情况下,不同的存储引擎的处理方式是不一样的。例如,MyISAM会将行拆成不同的片段存储,InnoDB则需要分裂页来是行可以放进页内。其他一些存储引擎也许从不在原数据位置更新数据。

  下面这些情况下使用varchar是合适的:

  1. 字符串列的最大长度比平均长度大很多;
  2. 列的更新很少,所以碎片不是问题;
  3. 使用了想UTF-8这样的复杂的字符集,每格字符都使用不同的字节数进行存储。

  在5.0或者更高的版本,MySQL在存储和检索时会保留末尾空格。但在4.1或者更老的版本,MySQL会剔除末尾空格。

char

  char类型是定长的:MySQL总是根据定义的字符串长度分配足够的空间。当存储char值时,MySQL会删除所有的末尾空格(4.1和更老版本中varchar也是这样实现的--也就是说这些版本中的char和varchar在逻辑上是一样的,区别只是在存储格式上)。char值会根据需要采用空格进行填充以方便比较。

  char适合存储很短的字符串,或者所有值都接近同一个长度。例如,char非常适合存储密码的MD5值,因为这是一个定长的值。对于经常变更的数据,char也比varchar更好,因为定长的char类型不容易产生碎片。对于非常短的列,char比varchar存储空间上也更有效率,例如用char(1)来存储只有Y和N的值,如果采用单字节字符集只需要一个字节,但是varchar(1)却需要两个字节,因为还有一个记录长度的额外字节。

  Tips 单字节字符集:记住字符串长度的定义不是字节数,是字符数。多字节字符集会需要更多的空间存储单个字符

char类型的这些行为可能有点难以理解,下面通过一个具体的列子来说明。首先,我们创建一张只有一个char(10)字段的表,并且往里面插入一些值:

mysql> create table char_test(char_col char(10));

insert into char_test(char_col)values('string1'),('  string2'),('string3  ');

当检索这些值的时候,会发现string3末尾的空格被截断了。

mysql> select concat("'",char_col,"'") from char_test;
+--------------------------+
| concat("'",char_col,"'") |
+--------------------------+
| 'string1' |
| ' string2' |
| 'string3' |
+--------------------------+

如果使用varchar(10)字段存储相同的值,结果如下:

mysql> select concat("'",varchar_col,"'") from varchar_test;
+-----------------------------+
| concat("'",varchar_col,"'") |
+-----------------------------+
| 'string1' |
| ' string2' |
| 'string3 ' |
+-----------------------------+

数据如何存储取决于存储引擎,并非所有的存储引擎都会按照相同的方式处理定长和变长的字符串。Memory引擎只支持定长的行,即使有变长字段也会根据最大长度分配最大空间。(Percona Server里的Memory引擎支持变长的行)。不过填充和截取空格的行为在不同的存储引擎都是一样的。因为这是在MySQL服务器层进行处理的。

  与char和varchar类似的类型还有binary和varbinary,它们存储的是二进制字符串。二进制字符串跟常规字符串非常相似,但是二进制字符串存储的是字节码而不是字符。填充也不一样:MySQL填充binary采用的是\0(零字节) 而不是空格,在检索时也不会去掉填充值。(如果需要在检索时保持值不变,则需要特别小心binary类型,MySQL会用\0将其填充到需要的长度。)

慷慨是不明智的

使用varchar(5)和使用varchar(200)存储'hello'的空间开销是一样的。那么使用更短的列有什么优势吗?

事实证明有很大的优势。更长的列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内部值。尤其是使用内存临时表进行排序或操作时会特别糟糕。在利用磁盘临时表进行排序同样糟糕。

所以,最好的策略是只分配真正需要的空间。

MySQL varchar和char类型的更多相关文章

  1. MySQL数据库中varchar与char类型的区别

    在数据库中建表时,需要给数据定义一个数据库中的数据库类型,当需要给String类型定义一个数据库中的类型时,可以看见有两个选择,一个是varchar,另一个是char,有很多人不清楚两者的区别,包括自 ...

  2. mysql varchar和char的根本区别深度详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt337 VARCHAR 和 CHAR 是两种最主要的字符串类型 .不幸的是,很 ...

  3. mysql varchar类型转换int类型找出最大值

    (1) 不严谨的,最简单的 select MAX(字段名 + 0) from 表名; (2) 使用函数实现 select MAX(cast(字段名 as SIGNED INTEGER)) from 表 ...

  4. mysql varchar类型转换int类型

    select * from gyzd_yysinfo order by cast(yysid as SIGNED INTEGER) 或者 select * from gyzd_yysinfo orde ...

  5. mysql varchar integer

    MySQL 中将 varchar 字段转换成数字进行排序 - MySQL - 大象笔记 https://www.sunzhongwei.com/order-by-varchar-field-which ...

  6. mysql中char,varchar与text类型的区别和选用

    关于char,varchar与text平时没有太在意,一般来说,可能现在大家都是用varchar.但是当要存储的内容比较大时,究竟是选择varchar还是text呢?不知道...... 于是去查阅了一 ...

  7. mysql中char,varchar与text类型的区别

      关于char,varchar与text平时没有太在意,一般来说,可能现在大家都是用varchar.但是当要存储的内容比较大时,究竟是选择varchar还是text呢?不知道...... text  ...

  8. MySQL数据库中的字段类型varchar和char的主要区别是什么?哪种字段查找效率要高?

    1,varchar与char的区别?(1)区别一,定长和变长,char表示定长,长度固定:varchar表示变长,长度可变.当插入字符串超出长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误 ...

  9. MySQL中VARCHAR与CHAR格式数据的区别

    区别 CHAR与VARCHAR类型类似,但它们保存和检索的方式不同.CHAR有固定的长度,而VARCHAR属于可变长的字符类型.它们最大长度和是否尾部空格被保留等方面也不同.在存储和检索过程中不进行大 ...

随机推荐

  1. hadoop中汉字与英文字符混合的keyword做为combine的key的问题

    近期,须要将汉字与字符的非常合串作为combine的输出的key, 这样做是希望,利用hadoop的归并来依照key进行分组,然后,在reduce阶段,拿到的都是一个一个组. 可是,发现,这样的,汉字 ...

  2. sessionStorage和localStorage之间的差别

    <!DOCTYPE html><html> <head lang="en"> <meta charset="utf-8" ...

  3. Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool

    原因:缺少commons-pool-X.jar包,到http://commons.apache.org/proper/commons-pool/download_pool.cgi下载后引入即可(地址可 ...

  4. 浅谈C中的指针和数组(七)

    现在到揭露数组名本质的时候了,先给出三个结论: (1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组: (2)数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量: ( ...

  5. Linux学习之服务器端口查看的方法

    1.用netstat查看: [grid@rac121 admin]$ netstat -anp | grep oracle (Not all processes could be identified ...

  6. QF——OC中的KVC,KVO

    KVC: (Key Value Coding) 键值编码 所谓KVC,其实就是不通过set和get方法访问对象属性,而是通过属性名字符串动态的去读取属性.KVC其实也是OC反射机制的一种运用. 之所以 ...

  7. 持续集成 之 apache-continuum

    作者:许振坪,http://blog.csdn.net/benkaoya 1.前言 最近在研究持续集成,摸索了很多持续集成的工具,Apache Continuum也包括其中.既然飞过,那就留下点什么吧 ...

  8. Html内容超出标记宽度后自动隐藏

    我们在显示长文本时,往往需要去在C#端去截取字符,但这绝对不是一个好方面,因为我们的长文本往往都是代HTML标记的,你一个载不好,就会出现乱码问题(出现半个HTML标记),而比较好的作法就是通过CSS ...

  9. 软件测试学习日志———— round 2 Junit+intellj idea 安装及简单的测试使用

    今天是软件测试的上机,主要内容是对junit的安装以及对一个简单类的测试实践.老师推荐用eclipse,但是我原来一直在 用intellj Idea,所以我试了试intellj Idea对junit的 ...

  10. DLR、ASTER GDEM、SRTM3、GMTED2010等5种全球高程数据对比

      目前网上有多种全球高程数据,国内在这方面也进步喜人,资源三号目前已放出来的卫片给了不少惊喜,其高程数值得期待.但资源三号的高程数据放出来还需等待,过去两三年全球高程数据发展相当迅猛,DLR放出了相 ...