思维导图

一、MySQL 的数据类型
在 MySQL 中,定义字段的类型对数据库的优化是非常重要的。
MySQL 支持多种类型,大致可以分为三类:
- 数值
- 日期/时间
- 字符串

(一)数值类型

示例:大整型
sql
age int
示例:小数型
sql
-- score(总长度, 小数点后保留的位数)
-- eg:数据范围0~100,小数点后两位
score(5, 2)
(二)日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

(三)字符串类型

1. 定长字符串 CHAR
举例:name char(10)
如果存储字符串'张三',虽然只有2个字符,但仍会占用10个字符空间
- 存储性能好:一律占用固定的字符空间
- 浪费空间
- 什么时候用?如果能确定字符的长度,比如存储性别
2. 变长字符串 VARCHAR
举例:name varchar(10)
如果存储字符串'张三',只会占用2个字符空间。
- 存储性能不佳:varchar需要先计算字符串长度,再进行存储,所以varchar的性能不佳。
- 节约空间
- 什么时候用?如果不能确定字符的长度,比如存储用户名
3. CHAR 和 VARCHAR 的对比
| 特性 | CHAR**(空间换性能)** | VARCHAR**(性能换空间)** |
|---|---|---|
| 类型 | 定长 | 变长 |
| 存储空间 | 固定长度 | 实际长度 + 1/2 字节 |
| 空间利用率 | 较低 | 较高 |
| 性能 | 读写更快(无需长度解析) | 读写略慢(需处理长度信息) |
| 适合场景 | 身份证、性别、国家代码 | 姓名、地址、备注、文章标题 |
ps:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
4. VARCHAR(n) 和 INT(n)
| 类型 | 括号里的 n 到底指什么 | 是否影响存储空间 | 是否影响可存数值/字符数 | 备注 |
|---|---|---|---|---|
| INT(n) | "显示宽度"(zerofill 时补零对齐) | ❌ 不决定字节数,始终是 4 B | ❌ 不限制数值大小 | 无 zerofill 时 n 完全没用;MySQL 8 已弃用显示宽度 |
| VARCHAR(n) | "字符数上限"(不是字节) | ✅ 实际存多少占多少 + 1~2 B 长度前缀 | ✅ 超出 n 会报错或截断 | UTF-8 下每个字符可能 1~4 B,但 n 仍按字符计数 |
- varcahr(n) 中的 n 代表 最多能存 n 个字符,它会影响存储空间和允许的长度。
- int(n) 中的 n 它不是存储长度,只是代表 显示宽度, 一般情况下没有意义,比如 int(1) 和 int(20) 存储和计算其实是一样的。
二、案例
需求: 设计一张学生表,请注重数据类型,长度的合理性
- 编号
- 姓名,姓名最长不超过10个汉字
- 性别,因为取值只有两种可能,因此最多一个汉字
- 生日,取值为年月日
- 入学成绩,小数点后保留两位
- 邮件地址,最大长度不超过64
- 家庭联系电话,不一定是手机号码,可能会出现 - 等字
- 学生状态(用数字表示,正常,休学,毕业...)
sql
create table student(
id int,
name varchar(10),
gender char(1),
birthday date,
score double(5,2),
email varchar(64),
tel varchar(15),
status tinyint
);

查询表格的结构信息:

三、相关面试题
varchar 与 char 的区别是什么?
CHAR(定长字符类型) ,是一种 固定长度 的字符串类型。占空间固定、读写快,适合固定长度字段。
VARCHAR(变长字符类型) ,是一种 可变长度 的字符串类型。空间利用率高,但读取时需要额外处理长度。
- 比如 char(128),不管存多长的字符串,它都会占满 128 个字符的空间;
- 而 varchar(128),只会按实际字符串长度占用空间,只要不超过 128 就行。
varchar(1000) 一定比 varchar(100) 好吗?
**等价问题:**既然varchar是变长,那是不是设置varchar(1000)一定比varchar(100)好?
不是这样的。虽然varchar是变长,在相同长度下,磁盘空间占用一样,将值设置更大一些,弹性空间也更大。但也不是完全没有代价的。
在内存加载的时候,每次都是按最大空间来分配的。显然,在排序场景,或者一些临时表聚合场景,更大空间会产生明显的不利影响。
提示:
varchar中的长度不光影响磁盘空间 ,还会影响在使用时的内存空间,并不是越长越好,这也是个常见且易踩坑的考点。
varchar 能完全代替 char 吗?
不能。varchar 的优点是更灵活。但是 char
也不是一无是处的。
- 首先,varchar 会额外用一个字节存储长度信息,而 char 则节约了一个字节;
- 其次,char 的存储空间都是一次性分配的,存储是固定连续的,而 varchar 的存储的长度是可变的,当 varchar
更改前后数据长度不一致时,就不可避免的会出现碎片的问题。针对上述情况,需要进行碎片消除作业,也是额外的成本。所以一般来说,长度固定的字段,还是用char比较合适,比如Hash,就很适合用 char。
为什么 VARCHAR 会碎片化?
VARCHAR 是可变长度类型,它的空间会随着内容的增删而变化。 当更新 VARCHAR
时,如果新内容比原来长,可能放不进原位置,InnoDB 就需要把它移动到别的页里,原位置留下空洞,久而久之就出现了碎片。
所以 VARCHAR 容易产生页分裂和空间碎片,而 CHAR 不会,因为 CHAR 是固定长度的。
varchar(11) 和 int(11) 中的 11 有什么区别?
varcahr 中的 11 代表
最多能存 11
个字符 ,它会影响存储空间和允许的长度。而 int 中的 11 它不是存储长度,只是代表
显示宽度 , 一般情况下没有意义,比如 int(1) 和 int(20)存储和计算其实是一样的。