MySQL CHAR和VARCHAR该如何选择


Posted in MySQL onMay 31, 2021

VARCHAR 和 CHAR 类型

VARCHAR 和 CHAR 是两种主要的字符串类型,用于存储字符。不幸的是,由于实现的方式依赖于存储引擎,因此很难解释这些字符串在磁盘和内存中如何存储,除了除了常用的 InnoDB 和 MyISAM 外,假设你使用了其他存储引擎,应当仔细阅读存储引擎的文档。​

VARCHAR 存储可变长度的字符串,也是最常用的字符数据类型。相比固定长度的类型,VARCHAR 所需的存储空间更小,它会尽可能少地使用存储空间(例如,短的字符串占据的空间)。对于 MyISAM 来说,如果创建表的时候指定了 ROW_FORMAT=FIXED 的话,那么会使用固定的空间存储字段而导致空间浪费。VARCHAR 使用1-2个额外的字节存储字符串的长度:当最大长度低于255字节的时候使用1个字节,如果更多的话就使用2个字节。因此,拉丁字符集的 VARCHAR(10)会使用11个字节的存储空间,而 VARCHAR(1000)则会使用1002个字节的存储空间。​

VARCHAR 由于能够节省空间,因此可以改善性能。但是,由于长度可变,当更新数据表的时候数据行的存储空间会变化,这一定程度上会带来额外的开销。如果数据行的长度导致原有的存储位置无法存放,那么不同的存储引擎会做不同的处理。例如 MyISAM 可能产生数据行的碎片,而 InnoDB 需要进行磁盘分页来存放更新后的数据行。​

通常,如果最大的列长度远远高于平均长度的话(例如可选的备注字段),使用 VARCHAR 是划算的,同时如果更新的频次很低,那么碎片化也不会是一个问题。需要注意的是,如果使用的是 UTF-8字符集,则实际存储的字节长度是根据字符定的。对于中文,推荐的存储字符集是 utf8mb4。​

CHAR 类型的长度是固定的,MySQL 会对每个字段分配足够的存储空间。存储CHAR 类型值的时候,MySQL 会移除后面多出来的空字符。值是使用空字符进行对齐以便进行比较。对于短的字符串来说,使用 CHAR 更有优势,而如果所有的值的长度几乎一致的话,就可以使用 CHAR。例如存储用户密码的MD5值时使用 CHAR 就更合适,这是因为 MD5的长度总是固定的。同时,对于字段值经常改变的数据类型来说,CHAR 相比 VARCHAR 也更有优势,因为 CHAR 不会产生碎片。对于很短的数据列,使用 CHAR 比 VARCHAR更高效,例如使用CHAR(1)存储逻辑值的 Y 和 N,这种情况下只需要1个字节,而 VARCHAR 需要2个字节。 对于移除空字符这个特性会感觉奇怪,我们举个例子:

CREATE TABLE t_char_varchar_test (
  id INT PRIMARY KEY,
  char_col CHAR(10),
  varchar_col VARCHAR(10)
);

INSERT INTO t_char_varchar_test 
VALUES 
(1, 'string1', 'string1'),
(2, '  string2', '  string2'),
(3, 'string3  ', 'string3  ');

按上面的结果插入数据表后,string2中的前置空格不会移除,但使用 CHAR 类型存储时,string3尾随空格会被移除,使用 SQL 查询结果来检验一下:

SELECT CONCAT("'", char_col, "'"), CONCAT("'", varchar_col, "'") 
FROM t_char_varchar_test WHERE 1

得出来的结果如下,可以看到 CHAR 类型的 string3后面的空格被移除了,而 VARCHAR类型的没有。这种情况大多数时候不会有什么问题,实际在应用中也经常会使用 trim 函数移除两端的空字符,但是如果确实需要存储空格的时候,那就需要注意不要选择使用 CHAR 类型:

MySQL CHAR和VARCHAR该如何选择

数据如何存储是由存储引擎决定的,而且存储引擎处理固定长度和可变长度的数据的方式并不相同。Memory 引擎使用固定大小的行,因此它需要分配最大可能的存储空间——即便数据长度是可变的。但是,对于字符串的对齐和空字符截断是由 MySQL 服务端完成的,因此所有存储引擎都是一样的。​

与 CHAR 和 VARCHAR 相似的是 BINARY和 VARBINARY,用于存储二进制字节字符,BINARY 的对齐使用字符0的字节值来对齐,并且再获取值的时候不会截断。如果需要使用字符的字节值而不是字符的话,使用 BINARY 会更高效,这是因为比较时,一方面不需要考虑大小写,另一方面是MySQL一次只比较一个字节。​

结语:

在实际数据表设计中,大多数情况下会选择使用 VARCHAR,但 VARCHAR 需要额外的1-2个字节存储字符串长度。需要注意的是在应用中最好能够限定字段的最大长度,从而可以使得数据表尽可能使用短的 VARCHAR来提高效率。同时,对于固定长度、长度很短或长度变化很小的字符类型,推荐使用 CHAR 类存储,以提高存储效率。

以上就是MySQL CHAR和VARCHAR的选择的详细内容,更多关于MySQL CHAR和VARCHAR的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL infobright的安装步骤
Apr 07 MySQL
教你用eclipse连接mysql数据库
Apr 22 MySQL
MySQL 不等于的三种使用及区别
Jun 03 MySQL
MySQL 时间类型的选择
Jun 05 MySQL
mysql中int(3)和int(10)的数值范围是否相同
Oct 16 MySQL
Mysql存储过程、触发器、事件调度器使用入门指南
Jan 22 MySQL
教你如何让spark sql写mysql的时候支持update操作
Feb 15 MySQL
一文搞清楚MySQL count(*)、count(1)、count(col)区别
Mar 03 MySQL
MySQL库表太大怎么办? 数据库分库分表项目实践
Apr 11 MySQL
MySQL脏读,幻读和不可重复读
May 11 MySQL
MySQL分布式恢复进阶
Jul 23 MySQL
SQL中去除重复数据的几种方法汇总(窗口函数对数据去重)
May 08 MySQL
带你学习MySQL执行计划
May 31 #MySQL
MySQL完整性约束的定义与实例教程
MySQL注入基础练习
解决Navicat for MySQL 连接 MySQL 报2005错误的问题
MYSQL(电话号码,身份证)数据脱敏的实现
May 28 #MySQL
MySql开发之自动同步表结构
mysql升级到5.7时,wordpress导数据报错1067的问题
May 27 #MySQL
You might like
一个简洁的PHP可逆加密函数(分享)
2013/06/06 PHP
使用迭代器 遍历文件信息的详解
2013/06/08 PHP
php面象对象数据库操作类实例
2014/12/02 PHP
PHP批量生成图片缩略图的方法
2015/06/18 PHP
php实现留言板功能(代码详解)
2017/03/28 PHP
Laravel 5.5官方推荐的Nginx配置学习教程
2017/10/06 PHP
THINKPHP-Apache服务器中使用Alias虚拟目录URL重写 隐藏index.php
2021/03/09 PHP
通过Mootools 1.2来操纵HTML DOM元素
2009/09/15 Javascript
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
基于jquery的finkyUI插件与Ajax实现页面数据加载功能
2010/12/03 Javascript
jquery背景跟随鼠标滑动导航
2015/11/20 Javascript
AngularJS基础 ng-value 指令简单示例
2016/08/03 Javascript
jQuery实用小技巧_输入框文字获取和失去焦点的简单实例
2016/08/25 Javascript
js判断是否为空和typeof的用法(详解)
2016/10/07 Javascript
微信小程序  modal详解及实例代码
2016/11/09 Javascript
JS树形菜单组件Bootstrap TreeView使用方法详解
2016/12/21 Javascript
浅谈 Vue v-model指令的实现原理
2017/06/08 Javascript
AngularJS集合数据遍历显示的实例
2017/12/27 Javascript
详解通过源码解析Node.js中cluster模块的主要功能实现
2018/05/16 Javascript
关于单文件组件.vue的使用
2018/09/20 Javascript
小程序如何在不同设备上自适应生成海报的实现方法
2019/08/20 Javascript
vue使用swiper实现中间大两边小的轮播图效果
2019/11/24 Javascript
vue Cli 环境删除与重装教程 - 版本文档
2020/09/11 Javascript
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
Python continue继续循环用法总结
2018/06/10 Python
使用Python实现图像标记点的坐标输出功能
2019/08/14 Python
使用matlab或python将txt文件转为excel表格
2019/11/01 Python
Python OpenCV视频截取并保存实现代码
2019/11/30 Python
Python中Selenium模块的使用详解
2020/10/09 Python
在pycharm中使用pipenv创建虚拟环境和安装django的详细教程
2020/11/30 Python
英国IT硬件供应商,定制游戏PC:Mesh Computers
2019/03/28 全球购物
小区停车场管理制度
2014/01/27 职场文书
营销与策划专业求职信
2014/06/20 职场文书
领导新年致辞2016
2015/07/29 职场文书
《普罗米修斯》教学反思
2016/02/22 职场文书
在Django中使用MQTT的方法
2021/05/10 Python