Value CHAR(4) Storage Required VARCHAR(4) Storage Required
'' '    ' 4 bytes '' 1 byte
'ab' 'ab  ' 4 bytes 'ab' 3 bytes
'abcd' 'abcd' 4 bytes 'abcd' 5 bytes
'abcdefgh' 'abcd' 4 bytes 'abcd' 5 bytes

 

  1. #官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
  2. #注意:char和varchar括号内的参数指的都是字符的长度
  3.  
  4. #char类型:定长,简单粗暴,浪费空间,存取速度快
  5. 字符长度范围:-(一个中文是一个字符,是utf8编码的3个字节)
  6. 存储:
  7. 存储char类型的值时,会往右填充空格来满足长度
  8. 例如:指定长度为10,存>10个字符则报错(严格模式下),存<10个字符则用空格填充直到凑够10个字符存储
  9.  
  10. 检索:
  11. 在检索或者说查询时,查出的结果会自动删除尾部的空格,如果你想看到它补全空格之后的内容,除非我们打开pad_char_to_full_length SQL模式(SET sql_mode = 'strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH';)
  12.  
  13. #varchar类型:变长,精准,节省空间,存取速度慢
  14. 字符长度范围:-(如果大于21845会提示用其他类型 mysql行最大限制为65535字节,字符编码为utf-:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
  15. 存储:
  16. varchar类型存储数据的真实内容,不会用空格填充,如果'ab ',尾部的空格也会被存起来
  17. 强调:varchar类型会在真实数据前加1-2Bytes的前缀,该前缀用来表示真实数据的bytes字节数(-2Bytes最大表示65535个数字,正好符合mysqlrow的最大字节限制,即已经足够使用)
  18. 如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit **8最大表示的数字为255
  19. 如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit **16最大表示的数字为65535
  20.  
  21. 检索:
  22. 尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容
  23.  
  24. charvarchar的介绍

char和varchar详细介绍

 

创建一个t1表,包含一个char类型的字段

  1. 创建一个t1表,包含一个char类型的字段
  2. create table t1(id int,name char());
  3. 超过长度:
  4. 严格模式下(报错):
  5. mysql> insert into t1 values('xiaoshabi');
  6. ERROR (): Data too long for column 'name' at row
  7. 非严格模式下(警告):
  8. mysql> set sql_mode='NO_ENGINE_SUBSTITUTION';
  9. Query OK, rows affected (0.00 sec)
  10.  
  11. mysql> create table t1(id int,name char());
  12. Query OK, rows affected (0.40 sec)
  13.  
  14. mysql> insert into t2 values('xiaoshabi');
  15. Query OK, row affected, warning (0.11 sec)
  16. 查看一下结果:
  17. mysql> select * from t1;
  18. +------+------+
  19. | id | name |
  20. +------+------+
  21. | | xiao | #只有一个xiao
  22. +------+------+
  23. row in set (0.00 sec)
  24. varchar类型和上面的效果是一样的,严格模式下也会报错。
  25.  
  26. 如果没有超过长度,那么char类型时mysql会使用空格来补全自己规定的char()的4个字符,varchar不会,我们来做个对比
  27. 例如:
  28. #再创建一个含有varchar类型的表t2
  29. 然后插入几条和t1里面相同的数据
  30. mysql>insert into t1 values(,'a'),(,'bb'),(,'ccc'),(,'d');
  31.  
  32. mysql>create table t2(id int,name varchar());
  33.  
  34. mysql> insert into t2 values(,'xiao'),(,'a'),(,'bb'),(,'ccc'),(,'d');
  35. 查看一下t1表和t2表的内容
  36. mysql> select * from t1;
  37. +------+------+
  38. | id | name |
  39. +------+------+
  40. | | xiao |
  41. | | a |
  42. | | bb |
  43. | | ccc |
  44. | | d |
  45. +------+------+
  46. rows in set (0.00 sec)
  47.  
  48. mysql> select * from t2;
  49. +------+------+
  50. | id | name |
  51. +------+------+
  52. | | xiao |
  53. | | a |
  54. | | bb |
  55. | | ccc |
  56. | | d |
  57. +------+------+
  58. rows in set (0.00 sec)
  59.  
  60. 好,两个表里面数据是一样的,每一项的数据长度也是一样的,那么我们来验证一下char的自动空格在后面补全的存储方式和varchar的不同
  61.  
  62. 通过mysql提供的一个char_length()方法来查看一下所有数据的长度
  63. mysql> select char_length(name) from t1;
  64. +-------------------+
  65. | char_length(name) |
  66. +-------------------+
  67. | |
  68. | |
  69. | |
  70. | |
  71. | |
  72. +-------------------+
  73. rows in set (0.00 sec)
  74.  
  75. mysql> select char_length(name) from t2;
  76. +-------------------+
  77. | char_length(name) |
  78. +-------------------+
  79. | |
  80. | |
  81. | |
  82. | |
  83. | |
  84. +-------------------+
  85. rows in set (0.00 sec)
  86. 通过查看结果可以看到,两者显示的数据长度是一样的,不是说好的char会补全吗,我设置的字段是char(),那么长度应该都是4才对啊?这是因为mysql在你查询的时候自动帮你把结果里面的空格去掉了,如果我们想看到它存储数据的真实长度,需要设置mysql的模式,通过一个叫做PAD_CHAR_TO_FULL_LENGTH的模式,就可以看到了,所以我们把这个模式加到sql_mode里面:
  87. mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
  88. Query OK, rows affected (0.00 sec)
  89.  
  90. 然后我们在查看一下t1t2数据的长度:
  91. mysql> select char_length(name) from t1;
  92. +-------------------+
  93. | char_length(name) |
  94. +-------------------+
  95. | |
  96. | |
  97. | |
  98. | |
  99. | |
  100. +-------------------+
  101. rows in set (0.00 sec)
  102.  
  103. mysql> select char_length(name) from t2;
  104. +-------------------+
  105. | char_length(name) |
  106. +-------------------+
  107. | |
  108. | |
  109. | |
  110. | |
  111. | |
  112. +-------------------+
  113. rows in set (0.00 sec)
  114. 通过结果可以看到,char类型的数据长度都是4,这下看到了两者的不同了吧,至于为什么mysql会这样搞,我们后面有解释的,先看现象就可以啦。
  115.  
  116. 现在我们再来看一个问题,就是当你设置的类型为char的时候,我们通过where条件来查询的时候会有一个什么现象:
  117. mysql> select * from t1 where name='a';
  118. +------+------+
  119. | id | name |
  120. +------+------+
  121. | | a |
  122. +------+------+
  123. row in set (0.00 sec)
  124. ok,结果没问题,我们在where后面的a后面加一下空格再来试试:
  125. mysql> select * from t1 where name='a ';
  126. +------+------+
  127. | id | name |
  128. +------+------+
  129. | | a |
  130. +------+------+
  131. row in set (0.00 sec)
  132. ok,能查到,再多加一些空格试试,加6个空格,超过了设置的char()的4
  133. mysql> select * from t1 where name='a ';
  134. +------+------+
  135. | id | name |
  136. +------+------+
  137. | | a |
  138. +------+------+
  139. row in set (0.00 sec)
  140. ok,也是没问题的
  141. 总结:通过>,=,>=,<,<=作为where的查询条件的时候,char类型字段的查询是没问题的。
  142. 但是,当我们将where后面的比较符号改为like的时候,(like是模糊匹配的意思,我们前面见过,show variables like '%char%';来查看mysql字符集的时候用过)
  143. 其中%的意思是匹配任意字符(0到多个字符都可以匹配到),还有一个符号是_(匹配1个字符),这两个字符其实就像我们学的正则匹配里面的通配符,那么我们通过这些符号进行一下模糊查询,看一下,char类型进行模糊匹配的时候,是否还能行,看例子:
  144. mysql> select * from t1 where name like 'a';
  145. Empty set (0.00 sec)
  146. 发现啥也没查到,因为char存储的数据是4个字符长度的,不满4个是以空格来补全的,你在like后面就只写了一个'a',是无法查到的。
  147. 我们试一下上面的通配符来查询:
  148. mysql> select * from t1 where name like 'a%';
  149. +------+------+
  150. | id | name |
  151. +------+------+
  152. | | a |
  153. +------+------+
  154. row in set (0.00 sec)
  155. 这样就能看到查询结果了
  156.  
  157. 试一下_是不是匹配1个字符:
  158. mysql> select * from t1 where name like 'a_';
  159. Empty set (0.00 sec)
  160. 发现一个_果然不行,我们试试三个_
  161. mysql> select * from t1 where name like 'a___';
  162. +------+------+
  163. | id | name |
  164. +------+------+
  165. | | a |
  166. +------+------+
  167. row in set (0.00 sec)
  168. 发现果然能行,一个_最多匹配1个任意字符。
  169. 如果多写了几个_呢?
  170. mysql> select * from t1 where name like 'a_____';
  171. Empty set (0.00 sec)
  172. 查不到结果,说明_匹配的是1个字符,但不是0-1个字符。
  173.  
  174. charvarchar测试

char和varchar测试

测试

测试结果总结:
  针对char类型,mysql在存储的时候会将不足规定长度的数据使用后面(右边补全)补充空格的形式进行补全,然后存放到硬盘中,但是在读取或者使用的时候会自动去掉它给你补全的空格内容,因为这些空格并不是我们自己存储的数据,所以对我们使用者来说是无用的。

  char和varchar性能对比:
    以char(5)和varchar(5)来比较,加入我要存三个人名:sb,ssb1,ssbb2
    char:
      优点:简单粗暴,不管你是多长的数据,我就按照规定的长度来存,5个5个的存,三个人名就会类似这种存储:sb ssb1 ssbb2,中间是空格补全,取数据的时候5个5个的取,简单粗暴速度快
      缺点:貌似浪费空间,并且我们将来存储的数据的长度可能会参差不齐

    varchar:
      varchar类型不定长存储数据,更为精简和节省空间
      例如存上面三个人名的时候类似于是这样的:sbssb1ssbb2,连着的,如果这样存,请问这三个人名你还怎么取出来,你知道取多长能取出第一个吗?(超哥,我能看出来啊,那我只想说:滚犊子!)
      不知道从哪开始从哪结束,遇到这样的问题,你会想到怎么解决呢?还记的吗?想想?socket?tcp?struct?把数据长度作为消息头。

      
      所以,varchar在存数据的时候,会在每个数据前面加上一个头,这个头是1-2个bytes的数据,这个数据指的是后面跟着的这个数据的长度,1bytes能表示2**8=256,两个bytes表示2**16=65536,能表示0-65535的数字,所以varchar在存储的时候是这样的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,所以存的时候会比较麻烦,导致效率比char慢,取的时候也慢,先拿长度,再取数据。
      优点:节省了一些硬盘空间,一个acsii码的字符用一个bytes长度就能表示,但是也并不一定比char省,看一下官网给出的一个表格对比数据,当你存的数据正好是你规定的字段长度的时候,varchar反而占用的空间比char要多。

官方解释


  1. #官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
  2. CHAR VARCHAR 是最常使用的两种字符串类型。
  3. 一般来说
  4. CHAR(N)用来保存固定长度的字符串,对于 CHAR 类型,N 的范围 ~
  5. VARCHAR(N)用来保存变长字符类型,对于 VARCHAR 类型,N 的范围为 ~
  6. CHAR(N)和 VARCHAR(N) 中的 N 都代表字符长度,而非字节长度。
  7. ps:对于 MySQL 4.1 之前的版本,如 MySQL 3.23 MySQL 4.0,CHAR(N)和 VARCHAR (N)中的 N 代表字节长度。
  8. #CHAR类型
  9. 对于 CHAR 类型的字符串,MySQL 数据库会自动对存储列的右边进行填充(Right Padded)操作,直到字符串达到指定的长度 N。而在读取该列时,MySQL 数据库会自动将 填充的字符删除。有一种情况例外,那就是显式地将 SQL_MODE 设置为 PAD_CHAR_TO_ FULL_LENGTH,例如:
  10. mysql> CREATE TABLE t ( a CHAR());
  11. Query OK, rows affected (0.03 sec)
  12. mysql> INSERT INTO t SELECT 'abc';
  13. Query OK, row affected (0.03 sec)
  14. Records: Duplicates: Warnings:
  15. mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;
  16. *************************** . row ***************************
  17. a: abc
  18. HEX(a):
  19. LENGTH (a):
  20. row in set (0.00 sec)
  21. mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
  22. Query OK, rows affected (0.00 sec)
  23. mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;
  24. *************************** . row ***************************
  25. a: abc
  26. HEX(a):
  27. LENGTH (a):
  28. row in set (0.00 sec)
  29. 在上述这个例子中,先创建了一张表 t,a 列的类型为 CHAR()。然后通过 INSERT语句插入值“abc”,因为 a 列的类型为 CHAR 型,所以会自动在后面填充空字符串,使其长 度为 。接下来在通过 SELECT 语句取出数据时会将 a 列右填充的空字符移除,从而得到 值“abc”。通过 LENGTH 函数看到 a 列的字符长度为 而非
  30. 接着我们将 SQL_MODE 显式地设置为 PAD_CHAR_TO_FULL_LENGTH。这时再通过 SELECT 语句进行查询时,得到的结果是“abc ”,abc 右边有 个填充字符 0x20,并通 HEX 函数得到了验证。这次 LENGTH 函数返回的长度为 。需要注意的是,LENGTH 函数返回的是字节长度,而不是字符长度。对于多字节字符集,CHAR(N)长度的列最多 可占用的字节数为该字符集单字符最大占用字节数 *N。例如,对于 utf8 下,CHAR()最 多可能占用 个字节。通过对多字节字符串使用 CHAR_LENGTH 函数和 LENGTH 函数, 可以发现两者的不同,示例如下:
  31. mysql> SET NAMES gbk;
  32. Query OK, rows affected (0.03 sec)
  33. mysql> SELECT @a:='MySQL 技术内幕 '; Query OK, rows affected (0.03 sec)
  34. mysql> SELECT @a,HEX(@a),LENGTH(@a),CHAR_LENGTH(@a)\G; ***************************** . row **************************** a: MySQL 技术内幕
  35. HEX(a): 4D7953514CBCBCCAF5C4DAC4BB
  36. LENGTH (a):
  37. CHAR_LENGTH(a):
  38. row in set (0.00 sec)
  39. @ a g b k , M y S Q L ”, 0x4D7953514CBCBCCAF5C4DAC4BB,LENGTH 函数返回 ,即该字符串占用 字节, 因为 gbk 字符集中的中文字符占用两个字节,因此一共占用 字节。CHAR_LENGTH 函数 返回 ,很显然该字符长度为
  40.  
  41. #VARCHAR类型
  42. VARCHAR 类型存储变长字段的字符类型,与 CHAR 类型不同的是,其存储时需要在 前缀长度列表加上实际存储的字符,该字符占用 ~ 字节的空间。当存储的字符串长度小 字节时,其需要 字节的空间,当大于 字节时,需要 字节的空间。所以,对 于单字节的 latin1 来说,CHAR()和 VARCHAR()最大占用的存储空间是不同的, CHAR()占用 个字节这是毫无疑问的,而 VARCHAR()的最大占用空间数是 字节,因为其需要 字节来存放字符长度。
  43. -------------------------------------------------
  44. 注意 对于有些多字节的字符集类型,其 CHAR VARCHAR 在存储方法上是一样的,同样 需要为长度列表加上字符串的值。对于 GBK UTF- 这些字符类型,其有些字符是以 字节 存放的,有些字符是按 字节存放的,因此同样需要 ~ 字节的空间来存储字符的长 度。
  45. -------------------------------------------------
  46. 虽然 CHAR VARCHAR 的存储方式不太相同,但是对于两个字符串的比较,都只比 较其值,忽略 CHAR 值存在的右填充,即使将 SQL _MODE 设置为 PAD_CHAR_TO_FULL_ LENGTH 也一样,例如:
  47. mysql> CREATE TABLE t ( a CHAR(), b VARCHAR());
  48. Query OK, rows affected (0.01 sec)
  49. mysql> INSERT INTO t SELECT 'a','a';
  50. Query OK, row affected (0.00 sec)
  51. Records: Duplicates: Warnings:
  52. mysql> SELECT a=b FROM t\G;
  53. *************************** . row ***************************
  54. a=b:
  55. row in set (0.00 sec)
  56. mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
  57. Query OK, rows affected (0.00 sec)
  58. mysql> SELECT a=b FROM t\G;
  59. *************************** . row ***************************
  60. a=b:
  61. row in set (0.00 sec)
  62. 官网详解

官网详解

其他的字符串类型:BINARY、VARBINARY、BLOB、TEXT

  

  1. BINARY VARBINARY 类似于 CHAR VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
  2. BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 BLOB 类型:TINYBLOBBLOBMEDIUMBLOB LONGBLOB。它们区别在于可容纳存储范围不同。
  3. TEXT 类型:TINYTEXTTEXTMEDIUMTEXT LONGTEXT。对应的这 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。
  4.  
  5. BLOB
  6. ._BLOB_text存储方式不同,_TEXT以文本方式存储,英文存储区分大小写,而_Blob是以二进制方式存储,不分大小写。
  7. ._BLOB存储的数据只能整体读出。
  8. ._TEXT可以指定字符集,_BLO不用指定字符集。

其他类型简单介绍

字符串char vchar性能对比补充的更多相关文章

  1. golang字符串拼接性能对比

    对比 +(运算符).strings.Join.sprintf.bytes.Buffer对字符串拼接的性能 package main import ( "bytes" "f ...

  2. 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)

    如果你觉得我的有些话有点唐突,你不理解可以想看看前一篇<C++之冒泡排序.希尔排序.快速排序.插入排序.堆排序.基数排序性能对比分析>. 这几天闲着没事就写了一篇<C++之冒泡排序. ...

  3. Storm VS Flink ——性能对比

    1.背景 Apache Flink 和 Apache Storm 是当前业界广泛使用的两个分布式实时计算框架.其中 Apache Storm(以下简称"Storm")在美团点评实时 ...

  4. C正则库做DNS域名验证时的性能对比

    C正则库做DNS域名验证时的性能对比   本文对C的正则库regex和pcre在做域名验证的场景下做评测. 验证DNS域名的正则表达式为: "^[0-9a-zA-Z_-]+(\\.[0-9a ...

  5. 不同Framework下StringBuilder和String的性能对比,及不同Framework性能比(附Demo)

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 介绍 环境搭建 测试用例 MSDN说明 ...

  6. PHP生成随机密码的4种方法及性能对比

    PHP生成随机密码的4种方法及性能对比 http://www.php100.com/html/it/biancheng/2015/0422/8926.html 来源:露兜博客   时间:2015-04 ...

  7. StringBuilder和string.Format性能对比

    本文由博主(YinaPan)原创,转载请注明出处:http://www.cnblogs.com/YinaPan/p/sbformat.html StringBuilder的性能优于string.For ...

  8. Net Core下多种ORM框架特性及性能对比

    在.NET Framework下有许多ORM框架,最著名的无外乎是Entity Framework,它拥有悠久的历史以及便捷的语法,在占有率上一路领先.但随着Dapper的出现,它的地位受到了威胁,本 ...

  9. 再看ExpressionTree,Emit,反射创建对象性能对比

    [前言] 前几日心血来潮想研究着做一个Spring框架,自然地就涉及到了Ioc容器对象创建的问题,研究怎么高性能地创建一个对象.第一联想到了Emit,兴致冲冲写了个Emit创建对象的工厂.在做性能测试 ...

随机推荐

  1. pymongo helper

    import pymongo import click # 数据库基本信息 db_configs = { 'type': 'mongo', 'host': '127.0.0.1', 'port': ' ...

  2. git clone速度太慢的解决办法

    最近发现使用git clone的速度比较慢,于是找到了办法分享给大家: 思路: git clone特别慢是因为github.global.ssl.fastly.net域名被限制了. 只要找到这个域名对 ...

  3. Java ArrayList,LinkedList使用

    1.ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上回在底层生成一个长度为10的Object类型数组. 2.如果增加的元素个数超过10个,那么Array ...

  4. ln bug

    /home/hdp/testcpy sudo ln -s . /usr/lib/cpy390sourcecode cpy390sourcecode -> . sudo ln -s pwd /us ...

  5. 深入理解JS中&&和||

    写了这么多JS,才发现JS的语法既是属于C语系的,又与一般C语系的编程语言某些地方有很大区别,其中&&和||就是其中一例. C语系中的&&和|| C语系的&&a ...

  6. hdfs 通过命令坏块监测和删除或者地址获取参数做监控

    [root@nodecm.oldboy.org.cn /data/dfs/nn/current]# hdfs fsck -list-corruptfileblocksConnecting to nam ...

  7. php递归注意事项

    /* 循环去除字符串左边的0 */ function removeLeftZero($str){ if($str['0'] == '0'){ $str = substr($str, '1'); rem ...

  8. pytorch对模型参数初始化

    1.使用apply() 举例说明: Encoder :设计的编码其模型 weights_init(): 用来初始化模型 model.apply():实现初始化 # coding:utf- from t ...

  9. svn使用步骤

    这里只是记录大概使用过程,操作步骤只供参考,不要按部就班. 1.安装SVN 服务端Setup-Subversion-1.6.5.msi和客户端TortoiseSVN-1.6.5.16974-win32 ...

  10. spring Securicty入门(一)

    在一次项目中启动测试一个借口,结果提示要登录,如下图.原因是无意中引用了spring Securicty的依赖,别的啥都没干就弹出来这个,懵逼了半天最后注释掉.shiro你引个jar包别的不配置,也不 ...