首页 > 数据库 >MySQL中char与varchar的区别:存储机制、性能差异、适用场景

MySQL中char与varchar的区别:存储机制、性能差异、适用场景

时间:2023-08-04 11:57:21浏览次数:41  
标签:00 varchar af 9b char 61 MySQL 20 e6

引用链接:https://www.maoyingdong.com/mysql-char-vs-varchar/  

在MySQL中,varchar和char都可以用来存储字符串。

从语义上看,varchar是变长的(Variable-length),char是定长的(Fixed-length)。

本文基于MySQL 5.7版本,从varchar和char的语义,到存储引擎底层存储机制,探讨它们在存储空间占用、查询性能上的区别。

测试环境

  • MySQL 5.7.36 版本
  • 存储引擎: Innodb
  • 行格式(Row format):DYNAMIC

Innodb存储引擎支持多种行格式(REDUNDANT、COMPACT、DYNAMIC、COMPRESSED),不同行格式存储方式存在差异。本文基于默认行格式DYNAMIC。

默认行格式可以通过innodb_default_row_format变量查看:

mysql> show variables like "innodb_default_row_format";
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
1 row in set (0.08 sec)
 

varchar和char在MySQL层的区别

根据MySQL的官方文档The CHAR and VARCHAR Types中的描述, varchar和char的区别主要有:

  • 最大长度:char是255,varchar是65535,单位是字符(而不是字节)。
  • 尾随空格:char会将尾随空格去掉,而varchar不会。
    因为存储时,char会用空格填充至指定长度,所以取出时需要去除空格。如果char字段有唯一索引,aa 会提示唯一索引冲突。
  • 存储空间占用:varchar会占用额外的1~2字节来存储字符串长度。如果最大长度超过255,就需要2字节,否则1字节。

注意:这是MySQL层的描述,具体怎么存储由存储引擎决定。

varchar和char在存储引擎层的区别

以下描述基于Innodb存储引擎、DYNAMIC行格式。

varchar如何存储

下面通过一个实验来看看,varchar在Innodb底层是如何存储的。

  1. 创建一个带有varchar字段的表格,并插入2条记录:

     
  1. mysql> select hex('毛');
    +------------+
    | hex('毛') |
    +------------+
    | E6AF9B |
    +------------+
    1 row in set (0.09 sec)
     

    1个“毛”字占用3个字节,插入的第1条中文“毛毛毛毛毛毛”占用18个字节, 对应上面标红的12(十六进制,转换为十进制是18)。类似的,第2条中文记录,100个汉字占用300个字节,对应上面标红的2c 812c 81是逆序存储,转过来之后是81 2c。其中第1位二进制位表示字符长度大于127字节,除去第1位后,即01 2c对应十进制的300)。

从上面的实验可以看出,varchar类型对于短字符串、长字符串、多字节编码,都是存储了实际的字符+字符长度。

char如何存储

接下来对比char类型的字符串,看看有什么区别。

  1. 先创建一个表格:

     
  1. mysql> insert into test_char values(1, "hello"),
    (2, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
    (3, "毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛毛");
    Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
     
  2. 再次使用hexdump命令查看文件中的数据:

    0000c060  02 00 1c 69 6e 66 69 6d  75 6d 00 04 00 0b 00 00  |...infimum......|
    0000c070  73 75 70 72 65 6d 75 6d  32 00 00 00 10 00 4a 00  |supremum2.....J.|
    0000c080  00 00 01 00 00 00 00 08  4a dc 00 00 01 dd 01 10  |........J.......|
    0000c090  68 65 6c 6c 6f 20 20 20  20 20 20 20 20 20 20 20  |hello           |
    0000c0a0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
    0000c0b0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
    0000c0c0  20 20 32 00 00 00 18 00  4a 00 00 00 02 00 00 00  |  2.....J.......|
    0000c0d0  00 08 4a dc 00 00 01 dd  01 1c 61 61 61 61 61 61  |..J.......aaaaaa|
    0000c0e0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
    0000c0f0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
    0000c100  61 61 61 61 61 61 61 61  61 61 61 61 96 00 00 00  |aaaaaaaaaaaa....|
    0000c110  20 ff 5d 00 00 00 03 00  00 00 00 08 4a dc 00 00  | .].........J...|
    0000c120  01 dd 01 28 e6 af 9b e6  af 9b e6 af 9b e6 af 9b  |...(............|
    0000c130  e6 af 9b e6 af 9b e6 af  9b e6 af 9b e6 af 9b e6  |................|
    0000c140  af 9b e6 af 9b e6 af 9b  e6 af 9b e6 af 9b e6 af  |................|
    0000c150  9b e6 af 9b e6 af 9b e6  af 9b e6 af 9b e6 af 9b  |................|
    0000c160  e6 af 9b e6 af 9b e6 af  9b e6 af 9b e6 af 9b e6  |................|
    0000c170  af 9b e6 af 9b e6 af 9b  e6 af 9b e6 af 9b e6 af  |................|
    0000c180  9b e6 af 9b e6 af 9b e6  af 9b e6 af 9b e6 af 9b  |................|
    0000c190  e6 af 9b e6 af 9b e6 af  9b e6 af 9b e6 af 9b e6  |................|
    0000c1a0  af 9b e6 af 9b e6 af 9b  e6 af 9b e6 af 9b e6 af  |................|
    0000c1b0  9b e6 af 9b e6 af 9b e6  af 9b 00 00 00 00 00 00  |................|
    0000c1c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    0000c1d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    

从上面内容可以看出,对于char类型的字段,innodb同样保存了字符长度(红色字体)。对于utf8mb4 char(50)来说,长度不够50字节的字符串,会使用空格(0x20)填充到50个字节(但不是最大长度200)。

char和varchar存储对比

  • char和varchar都会存储字符串长度
  • 对于CHAR(N)字段,如果实际存储数据小于N字节,会填充空格到N个字节。

性能对比

从char和varchar的存储结构对比,可以得出一个结论:char填充空格可能导致浪费存储空间,进而导致性能下降。因为char多存储一些空格,意味着需要从磁盘读写更多的数据、耗费更多内存、查找数据时删除空格可能也会耗费一些CPU性能。

那与varchar相比,char字段是不是一无是处呢?

大部分情况,是的,最好使用varchar。不过考虑一个极端的场景:某个字段的最大长度是100字节,但是会频繁修改。如果使用char(100),则插入记录后就分配了100个字节,后续修改不会造成页分裂、页空隙等问题,而varchar(100)由于没有提前分配存储空间,后续修改时可能出现页分裂,进而导致性能下降。

   char和varchar 使用场景 char  适应于固定长度的码值、定值;更新次数多的小长度字段; varchar 适应于不定的字段,如审核意见、理由;更新次数少的字段;系统性能需要;

标签:00,varchar,af,9b,char,61,MySQL,20,e6
From: https://www.cnblogs.com/sumingyi/p/17605496.html

相关文章

  • MySql基础及约束
    review#数据库#MySQL数据库数据库基础知识存储数据的仓库,数据是有组织的存储的英文:database,简称DB数据库管理系统是管理数据库的大型软件,英文为DataBaseManagermentSystem简称DBMS关系表数据库SQl是结构化查询语言,用来操作关系型数据库,定义了操作所有关系型数据库......
  • 数据格式的处理 echarts数据改为 Table表格格式的数据
      前景后端返回的echarts展示数据格式,既要展示echarts又要展示table表格,echarts的数据格式为下面{xData:['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],yData1:[10,52,200,334,390,330,220],yData2:......
  • TwinCAT3 Database Server 模块的使用步骤(以MySQL为例)
    1.首先安装Mysql和Twincat3TF6420-Database-Server.exe2.在Mysql中创建数据库,以测试为目的,所以简单创建了两个 3.Twincat3可以在项目中添加,或者可以直接在菜单栏的Configurator中配置 连接的数据库的类型为NET_MySQL,由于拓扑是均基于一台IPC,所以可以选择localhost,数据库......
  • echarts多次setOption没有覆盖上一条数据 和 echarts的站位问题
    1、问题现象:echarts第一次获取的数据展示后第二次再次获取会覆盖不了展示的依然是上次的数据解决办法:chart.clear()   2、问题现象:echarts的占位没有数据的话是只展示x轴和y轴解决办法:利用title的副标题subtext,默认为“暂无......
  • mysql集群高可用搭建
    mysql galera集群模式    mysql节点多主模式    对任意一个节点的mysql操作都会实时同步到集群中的所有节点mysql上 使mysql集群像是无状态对外提供服务首节点安装rpm-epostfix-2:2.10.1-9.el7.x86_64rpm-emariadb-libs-5.5.68-1.el7.x86_64rp......
  • MySQL配置通过systemctl管理
     MySQL配置通过systemctl管理 参考官方文档资料,步骤不多。创建mysqld.service文件。touch/usr/lib/systemd/system/mysqld.servicechmod644/usr/lib/systemd/system/mysqld.service  官方对MySQL5和MySQL8提供的mysqld.service内容并不同。/etc/sysconfig/mysq......
  • python + mysql
    1.连接mysql数据库,基本数据查询流程#1.连接conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',password='',db='db8',charset='utf8')#2.创建游标cursor=conn.cursor()#注意%s需要加引号sql="select*fromu......
  • 使用echarts画流程图-2
    效果图代码vardata=[{name:'数据中心人员专题库',tooltip:{formatter:'{b}:19999<br/>'},value:[10,0],symbol:'image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAyCAYAAAAA9rgCAAA......
  • MySQL查询语句(1)
    连接数据库mysql-hlocalhost-uroot-prootDQL-介绍DQL英文全称是DataQueryLanguage(数据查询语言),数据查询语言,用来查询数据库中表的记录查询SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字......
  • mysql插入报错java.sql.SQLException: Incorrect string value: '\xF0\x9F\x87\xA
    背景环境java8,centos7.9,mysql8.0.34新装的环境,默认给装了mysql8,想着与时俱进用下新版,结果插入就报错java.sql.SQLException:Incorrectstringvalue:'\xF0\x9F\x87\xA8\xF0\x9F...'forcolumn解决方法这个错误通常是由于MySQL数据库中的字符集不支持存储特定的字符或表情符......