当前位置: 首页 > ds >正文

MySQL数据类型之VARCHAR和CHAR使用详解

在设计数据库字段时,字符串类型算是最常见的数据类型之一了,这篇文章带大家深入探讨一下MySQL数据库中VARCHARCHAR数据类型的基本特性,以及它们之间的区别。

VARCHAR类型

VARCHAR(Variable Character,可变长度字符)是一种用于存储可变长度字符串的数据类型,可指定存储数据的最大长度。

VARCHAR是存储字符串最广泛使用的数据类型之一。在定义VARCHAR字段时,通常使用VARCHAR(n)格式指定该字段的最大字符容量,其中n是允许存储的字符最大数量。

每个VARCHAR字段可以设置一个最大长度值,从1到65535字符(根据MySQL的存储引擎和行格式限制)。不过,该长度会受到一些因素的影响,例如:

  • 表的字符集会影响字段的最大字节数。例如,在一个utf8mb4表中,每个字符可能占用最多4字节,因此要确保总长度(包括所有列和其它数据)适配MySQL的行存储限制。
  • 行存储限制约为65535字节,因此要在表中合理设计列类型。

由于VARCHAR是一种可变长度类型,数据库会根据实际存储的字符串长度动态分配足够的存储空间,而不是预先分配最大限定长度的空间。除了存储字符串内容外,还会存储一些额外的元数据。

VARCHAR数据类型使用额外的长度指示字节存储字符串的长度:

  • 如果字符串长度小于255字节(一个VARCHAR列的定义最大长度为255字符),则使用1个字节来记录长度;
  • 如果字符串长度超过255字节,则需要2个字节来记录长度。

CHAR类型

CHAR是MySQL中的一种字符数据类型,最大长度为255个字符,主要用于存储固定长度的字符串。无论插入的数据是否达到了定义的长度,CHAR都会根据其设定的长度自动填充空格(使用空格补齐),以确保其值总是固定长度。它适用于那些长度固定的、不经常变化的字符串,比如国家代码、省份缩写等。

当一个列的类型定义为CHAR类型后,列中的内容的长度就是字段定义的长度(字符数)。如果写入CHAR列中的字符串的长度小于指定的字符长度,MySQL会在源字符串后填充空格一直到指定的长度。当读取CHAR列中的值时,MySQL会删除后面的空格。

由于CHAR数据类型采用固定的长度进行存储,因此CHAR的性能要比VARCHAR更好。

VARCHAR类似,可以使用CHAR(n)格式来设置字段的最大字符数。如果未指定,n默认为1。在CHAR列中存储的值会右对齐用空格填充,因此不管要保存的字符串内容如何,它始终会存储n个字符。

字符集对字段存储的影响

在数据库设计中,字符集 (Character Set) 和排序规则 (Collation) 是重要的环节。字符集决定了可以存储哪些字符以及每个字符所需的空间,而排序规则决定了数据如何比较和排序。

数据库在日常使用中,除了要支持英文字符之外,还需要支持像西班牙语中的特殊字符 “Ñ”,以及像日语中的 “データベース” 或中文中的 “数据库” 等复杂字符。为此,MySQL提供了多种字符集(charset),如 latin1(用于基本英文字符)、utf8(支持大部分语言)、utf8mb4(支持完整的 Unicode,包括表情符号)。

字符集不仅影响文本在数据库中的存储形式,也直接影响该字段的存储空间效率。不同字符集的每个字符所需的字节数不同,具体如下:

  • latin1: 每个字符固定占用 1 个字节。
  • utf8: 每个字符占用 1~3 个字节。
  • utf8mb4: 每个字符占用 1~4 个字节(主要用于完整的 Unicode,例如表情符号)。

在使用VARCHAR字段时,定义的最大长度n指的是字符的数量,而不是具体存储所需的字节数。由于字符集影响每个字符的数据大小,因此实际存储时需要考虑字符占用的字节数以及MySQL的行存储限制。

MySQL中,每行数据的最大存储限制为65,535 字节,这包括所有列的数据以及其他额外信息(如长度字节、行偏移量等)。

字符集对CHAR类型的影响与VARCHAR类型类似,但由于CHAR是固定长度存储,影响的性质稍有不同。CHAR无论存储的字符数量是多少,总会为字段定义的最大长度分配固定空间。例如,在utf8mb4下,一个CHAR(255)字段最大可能需要255 × 4 = 1,020字节。

由于CHAR是固定长度存储类型,在多字节字符集下往往存在空间浪费问题,因此在合理选择字段数据类型时,需要结合应用场景、字符集及数据特性来做对应的设计。

数据可视化的差异

当数据存储到CHAR字段时,其副作用之一是字符串中的所有尾随空格会在保存时被忽略。实际查询时,MySQL不会返回这些尾随空格,因为它会假设这些空格仅仅是数据类型的填充部分。

用具体的实例演示一下,创建一个表,其中有两个列:VARCHAR(20)CHAR(20)。接下来插入一些尾部有5个空格的数据,并观察它们的存储情况。

CREATE TABLE strings(id INT PRIMARY KEY AUTO_INCREMENT,variable VARCHAR(20),fixed CHAR(20)
);INSERT INTO strings (variable, fixed) VALUES ("Drifter     ", "Drifter     ");

如果运行以下SELECT语句,表面上看返回的数据是相同的:

SELECT * FROM strings;

img

但如果使用CHAR_LENGTH函数来计算每个字段实际使用的字符数,就会发现差异。VARCHAR字段(用varchar_data_length表示)显示为12,其中包括结尾的5个空格字符,而CHAR字段仅显示为7。

这是因为MySQL存储了VARCHAR值末尾的空格,但认为CHAR值的末尾空格只是填充,因此忽略了这一部分数据。

SELECT CHAR_LENGTH(variable) AS varchar_data_length, CHAR_LENGTH(fixed) AS char_data_length FROM strings;

img

字段存储空间示例

当数据写入磁盘时,VARCHAR值会有额外的开销。如果存储字符串 “Spider”(长度为6个字符)到VARCHAR(6)CHAR(6)的字段中,以utf8mb4字符集为例,以下是磁盘空间消耗情况:

  • VARCHAR值占用25字节(每字符4字节 + 1字节开销)。
  • CHAR值占用24字节(每字符4字节,无额外开销)。

如果存储字符串 “Eido” 到这些字段,以下结果会发生变化:

  • VARCHAR只使用17字节,因为它是可变长度。
  • CHAR保持使用24字节,因为它是固定长度且右填充了2个空格。

字段存储对照表如下:

VARCHAR(6) 存储值VARCHAR(6) 使用空间CHAR(6) 存储值CHAR(6) 使用空间
“Spider”“Spider”25 字节“Spider”24 字节
“Eido”“Eido”17 字节"Eido "24 字节
"Eido ""Eido "25 字节"Eido "24 字节

小结

最后,总结一下本文的关键点:

  • VARCHAR特点:可变长度,适用于存储长度不固定的字符串,并且根据实际数据长度动态分配空间。
  • CHAR特点:固定长度,有性能优势,但可能导致存储空间浪费,适用于长度固定的字符串。
  • 字符集影响:字符集决定了每个字符的字节数,以及存储时所需的空间大小,如utf8mb4需要1~4字节。
  • 数据存储差异:VARCHAR保留尾部空格且会增加长度指示字节,CHAR填充尾部空格但在查询时忽略。
  • 空间消耗对比:VARCHAR更节省空间,但有附加开销;CHAR采用固定空间,适合少量数据且不受字符长度变化影响。

在数据库设计中,VARCHAR和CHAR是两种常见的字符串存储类型,它们各有适用场景和性能特点。在选择字段类型时,应充分考虑数据的变化形态、存储性能和空间效率。

http://www.xdnf.cn/news/6522.html

相关文章:

  • 基于大模型预测围术期麻醉苏醒时间的技术方案
  • Ubuntu 安装 Redis
  • 《Adversarial Sticker: A Stealthy Attack Method in the Physical World》论文分享(侵删)
  • A2O娱乐李秀满纪录片首映礼,A2O MAY、少女时代、崔始源、泰民齐聚祝贺
  • 脚本语言Lua
  • 使用PEFT库将原始模型与LoRA权重合并
  • 视频分辨率增强与自动补帧
  • ‌JMeter聚合报告中的任务数和并发数区别
  • 【HarmonyOS 5】鸿蒙mPaaS详解
  • MySQL 开发的智能助手:通义灵码在 IntelliJ IDEA 中的应用
  • Python网络请求利器:urllib库深度解析
  • 单片机-STM32部分:16、Git工具使用
  • 计算图存储采用矩阵吗,和张量关系
  • linux libdbus使用案例
  • 15.springboot-控制器处理参数传递
  • 2025年山东省数学建模F题思路
  • PostgreSQL MCP 使用案例
  • 动态规划问题 -- 多状态模型(买股票的最佳时机II)
  • Vue组件-霓虹灯:技术解析与实现
  • OpenCV CUDA模块中矩阵操作-----矩阵最大最小值查找函数
  • 产品销量数据爬虫通用模板
  • js关于number类型的计算问题
  • msf安卓远控木马手动捆绑正常apk
  • LLM中最后一个位置的对数概率是什么? 怎么作为LOSS实现方式
  • C++23 新特性:ranges::contains 与 ranges::contains_subrange
  • 线代第二章矩阵第九、十节:初等变换、矩阵的标准形、阶梯形与行最简阶梯形、初等矩阵
  • RPA 自动化实现自动发布
  • 基于matlab实现AUTOSAR软件开发---答疑6
  • 瓶装燃气送气工考试的实操考核内容有哪些?
  • Python训练营打卡 Day26