MySQL - 数据类型

字段类型

整型

类型 位数 占用字节 无符号取值范围 有符号取值范围
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 |
+---------------------+