字段类型
整型
类型 | 位数 | 占用字节 | 无符号取值范围 | 有符号取值范围 |
---|---|---|---|---|
TINYINT | 8 | 1字节 | -128 ~ 127 | 0 ~ 255 |
SMALLINT | 16 | 2字节 | -32,768 ~ 32,767 | 0 ~ 65,535 |
MEDIUMINT | 24 | 3字节 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 |
INT | 32 | 4字节 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 |
BIGINT | 64 | 5字节 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | 0 ~ 18,446,744,073,709,551,615 |
整型相关问题说明:
1.存储位数与字节换算
- 1字节 = 8位数,所以位数与占用字节属于相辅相成关系。
2.数值范围计算逻辑
- 有符号数:取值范围为
-2^(n-1) ~ 2^(n-1)-1
例如:TINYINT有符号范围-2^7 ~ 2^7-1 = -128 ~ 127
- 无符号数:取值范围为
0 ~ 2^n-1
例如: TINYINT无符号范围 =0 ~ 2^8-1 = 0 ~ 255
3.为什么"越小的列越好"?
- 节省存储空间:更小的数据类型减少磁盘和内存占用
- 提升性能:CPU处理小范围整数更快,索引效率更高
例如:存储年龄(0 ~ 200)--> 使用 TINYINT UNSIGNED(1字节)而非 INT(4字节)
存储商品( ≤6W ) --> 使用 SMALLINT UNSIGNED(2字节)而非 INT(4字节)
4.数据类型常见误区
- 以 INT(11) 为例子:括号中的数字(11)是显示宽度,仅影响交互工具(如 MySQL 客户端)的显示格式,与存储和计算无关
- 实际存储范围由数据类型决定:
INT 始终是4字节,无轮 INT 显示宽度是 INT(11) 还是 INT(3)
若字段定义为 INT(3) ZEROFILL,数值5会显示为005,但存储空间不变
浮点数
类型 | 占用字节 | 精度 | 存储方式 |
---|---|---|---|
FLOAT | 4字节 | 约7位有效数字 | 32位浮点数(IEEE 754) |
DOUBLE | 8字节 | 约15位有效数字 | 64位浮点数(IEEE 754) |
DECIMAL(NUMERIC) | 变长(每4字节存储9位数字) | 精确小数(无精度损失) | 字符串形式存储的定点数 |
浮点数相关问题说明:
1.为什么浮点数不精确?
- 浮点数的二进制表示缺陷
部分十进制小数无法精确转换位二进制浮点数(例如 0.1),导致微小的舍入误差
示例:
sql
CREATE TABLE test_fp (f FLOAT, d DECIMAL(10,2));
INSERT INTO test_fp5 VALUES (0.1, 0.1);
SELECT CAST(f AS DECIMAL(30,20)) AS f_exact,d FROM test_fp;
+--------------------------------+-------------+
| f_exact | d |
+--------------------------------+-------------+
| 0.10000000149011612000 | 0.10 |
| 123456792.00000000000000000000 | 0.00 |
| 123456792.00000000000000000000 | 12345678.00 |
+--------------------------------+-------------+
2.DECIMAL类型详解
- 定义格式
sql
DECIMAL(M,D)
M(总位数):整数部分+小数部分的总位数(默认M=10)
D(小数位数):小数点后的位数(默认D=0)
- 存储空间计算
每9位数字占用4字节,剩余位数按比例分配
例如:
sql
DECIMAL(18,9) --> 整数9位+小数9位 = 总18位 --> 占用 4+4=8 字节
DECIMAL(10,3) --> 总10位 --> 占用 5字节(4字节前9位,1字节剩余1位)
3.FLOAT(M,D)的误导性
- M和D不改变存储空间:FLOAT(7,3)和FLOAT均为4字节存储
- 实际作用:仅约束插入值的范围(例如FLOAT(7,3)允许整数部分最多4位),但不影响存储精度
字符串
数据类型 | 存储方式 | 最小存储空间 | 空格处理 | 最大长度 | 适用场景 |
---|---|---|---|---|---|
CHAR | 固定长度 | 定义的长度 | 删除末尾空格 | 255字符 | 长度固定的数据(MD5,状态码) |
VARCHAR | 可变长度 | 数据实际长度+长度前缀(1-2字节) | 保留末尾空格 | 65535字节(受行大小限制) | 长度变化较大的数据(用户名,地址) |
1.存储机制讲解
CHAR的定长存储
- 填充机制:若数据长度 < 定义长度,右侧用空格填充至定义长度
VARCHAR的变长存储
-
长度前缀:存储数据实际长度,占用1-2字节
- 数据 ≤ 255字节 --> 1字节前缀
- 数据 > 255字节 --> 2字节前缀
数据类型的更新行为
-
CHAR:定长存储,更新后长度不变(无需重组存储空间)
-
VARCHAR:若更新后,数据长度增加并超出原存储容量(触发页分裂或行迁移)
- 不同存储引擎处理方式
存储引擎 | 处理方式 | 性能影响 |
---|---|---|
MyISAM | 将行拆分为多个片段存储 | 读取时需要重组数据,影响查询速度 |
InnoDB | 分裂页存储 | 写入延迟增加,可能导致页内碎片话,空间利用率下降 |
时间和日期
特性 | DATETIME | TIMESTAMP |
---|---|---|
时间范围 | 1001-01-01 00:00:00 ~ 9999-12-31 23:59:59 | 1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC |
存储空间 | 8字节 | 4字节 |
时区处理 | 按字面值存储,与时区无关 | 存储为UTC时间,查询时转换到当前时区 |
自动化支持 | 不支持 | 支持(默认CURRENT_TIMESTAMP) |
2038年问题 | 无 | 2038年后溢出报错 |
默认精度 | 秒级(MySQL 5.6+支持微秒) | 秒级(MySQL 5.6+支持微秒) |
1.存储机制讲解
DATETIME
- 存储格式:按
YYYYMMDDHHMMSS
的整数形式存储,例如20250521143000
- 时区无关:存入和读取的值始终与写入时字面值一致
sql
CREATE TABLE test_datetime(dt_col datetime);
INSERT INTO test_datetime (dt_col) VALUES ('2023-05-21 14:30:00');
SELECT * FROM test_datetime;
+---------------------+
| dt_col |
+---------------------+
| 2023-05-21 14:30:00 |
+---------------------+
TIMESTAMP
- 存储格式:存储为UTC时间戳(距离1970-01-01 00:00:00的秒数)
- 时区敏感:存入时转换为UTC,读取时转换为当前时区
sql
CREATE TABLE test_timestamp(ts_col timestamp);
INSERT INTO test_timestamp (ts_col) VALUES ('2023-05-21 14:30:00');
SHOW GLOBAL VARIABLES like "time_zone";
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| time_zone | SYSTEM |
+---------------+--------+
SELECT * FROM test_timestamp;
+---------------------+
| ts_col |
+---------------------+
| 2023-05-21 14:30:00 |
+---------------------+
SET time_zone = '+00:00';
SELECT * FROM test_timestamp;
+---------------------+
| ts_col |
+---------------------+
| 2023-05-21 06:30:00 |
+---------------------+