数据库设计原则

目录

在满足需求的前提下,尽量选择占用空间小的数据类型

好处

一、数值类型

[1. 整数类型](#1. 整数类型)

[2. 小数/浮点数类型](#2. 小数/浮点数类型)

二、字符串类型

三、日期与时间类型

四、其他类型


在满足需求的前提下,尽量选择占用空间小的数据类型

好处

  • 减少磁盘 I/O:数据页能容纳更多行,查询时一次性读入内存的有效数据更多,速度更快。
  • 减少内存占用:数据库缓冲池可以缓存更多的数据页,提高缓存命中率。
  • 提升网络传输效率:特别是在分布式数据库或客户端/服务器架构中,返回结果集的数据量更小。

一、数值类型

1. 整数类型
类型 字节 有符号范围 无符号范围 适用场景
TINYINT 1 -128 ~ 127 0 ~ 255 状态标志 (如:0-禁用,1-启用)、年龄小范围分类ID
SMALLINT 2 -32,768 ~ 32,767 0 ~ 65,535 年份中期分类ID城市ID端口号
MEDIUMINT 3 -8,388,608 ~ 8,388,607 0 ~ 16,777,215 不太常用,可作为INTSMALLINT之间的折中
INT 4 -2^31 ~ 2^31-1 0 ~ 2^32-1 最常用的整数类型。用户ID、订单ID、大分类ID、数量等。
BIGINT 8 -2^63 ~ 2^63-1 0 ~ 2^64-1 自增主键(当数据量极其庞大时)、雪花算法ID、金融领域的大额金额(以分为单位)

选择建议:

  • 优先选择无符号 UNSIGNED :如果你的数据确定不会是负数(如ID、年龄、数量),一定要加上UNSIGNED,这能让你在同样的字节数下使用更大的正数范围。

  • 能用TINYINT就别用INT :比如性别字段,用01表示就足够了,用INT会浪费3个字节。

2. 小数/浮点数类型
类型 字节 特点 适用场景
FLOAT 4 单精度浮点数,近似计算 对精度要求不高的科学计算、传感器数据
DOUBLE 8 双精度浮点数,近似计算 需要更大范围或精度的科学计算
DECIMAL(M, D) 变长 精确小数,M是总位数,D是小数位 金融、货币相关 (如:金额DECIMAL(10,2))、需要精确计算的数值

选择建议:

  • 精确计算用 DECIMAL :凡是和钱有关的,必须用DECIMAL,避免浮点数精度丢失。

  • 非精确计算用 FLOAT/DOUBLE:比如存储一个产品的平均评分、经纬度等,这些数据本身就不绝对精确,可以使用浮点数以节省空间。

二、字符串类型

类型 最大长度 特点 适用场景
CHAR(N) 255字符 定长。不足长度会用空格填充。存取效率高。 长度固定或几乎固定的短字符串 。例如:MD5哈希值(32位)、UUID(36位)、国家代码(如'CN','US')、枚举代码(如'M', 'F')。
VARCHAR(N) 65,535字节 变长。只用空间存储实际内容,前面有1-2个字节记录长度。 绝大多数字符串场景 。例如:用户名、邮箱、地址、标题、描述。关键是合理设置N,不要盲目给很大值
TINYTEXT 255字节 变长 短文本、缓存内容
TEXT 64KB 变长 文章正文、帖子内容、商品详情
MEDIUMTEXT 16MB 变长 更大的文本,如书籍内容、代码日志
LONGTEXT 4GB 变长 极大的文本

选择建议:

  • 定长与变长:CHAR和VARCHAR的选择是经典问题。如果字段长度变化不大(比如都是2个字符或都是32个字符),用CHAR(N)效率更高。如果长度变化很大(比如用户名从3字符到20字符),用VARCHAR(N)更省空间。
  • 不要过度使用 TEXT:TEXT类型的设计初衷是存储大段文本。对于像"用户昵称"、"商品标题"这种长度有限的字段,应该优先使用VARCHAR并设置一个合理的上限(如VARCHAR(100))。因为TEXT类型有额外的开销,且通常不能有默认值。
  • 为 VARCHAR 设置合理的长度:VARCHAR(100)和VARCHAR(500)在存储"Hello"时占用的空间是一样的。但为什么不全设为500?因为:
    1. 内存临时表:MySQL在内存中创建临时表时会使用定义的长度,过大的N会浪费内存。
    2. 前端和后端校验也会依赖这个长度。

三、日期与时间类型

类型 字节 格式 范围 适用场景
DATE 3 'YYYY-MM-DD' '1000-01-01' ~ '9999-12-31' 仅需要日期,如生日、入职日期、创建日期(如果不需要时间)
TIME 3 'HH:MM:SS' '-838:59:59' ~ '838:59:59' 仅需要时间,如会议时间、定时任务时间
DATETIME 8 'YYYY-MM-DD HH:MM:SS' '1000-01-01 00:00:00' ~ '9999-12-31 23:59:59' 需要完整的日期和时间 ,如订单创建时间、日志记录时间。与时区无关
TIMESTAMP 4 'YYYY-MM-DD HH:MM:SS' '1970-01-01 00:00:01' UTC ~ '2038-01-19 03:14:07' UTC 记录数据行的最后修改时间 、需要自动更新时间 的字段、需要时区转换 的场景。与时区有关
YEAR 1 'YYYY' 1901 ~ 2155 只需要存储年份,如毕业年份、产品发布年份

选择建议:

  • TIMESTAMP vs DATETIME:
    • 空间:TIMESTAMP只要4字节,是DATETIME的一半,优先考虑。
    • 功能:TIMESTAMP会自动转换为UTC时间存储,并在检索时转换回当前时区。可以设置ON UPDATE CURRENT_TIMESTAMP自动更新。
    • 范围:TIMESTAMP有2038年问题,如果需要存储更久远的时间,必须用DATETIME。
  • 只存日期就用 DATE:比如birthday字段,用DATE比用DATETIME或TIMESTAMP节省很多空间。

四、其他类型

  • ENUM:枚举类型。在内部用整数存储,但显示为字符串。非常适合状态、类型等固定类别的字段。

    • 优点:非常紧凑。

    • 缺点:增加新的枚举值需要修改表结构。

    • 场景status ENUM('pending', 'active', 'inactive')

  • SET:集合类型。可以存储多个枚举值。

    • 场景:用户标签、权限位。
  • BIT(M):位字段类型。M是位数(1-64)。

    • 场景:存储真正的位标志,如一个字节(BIT(8))存储8个布尔开关。
  • BLOB :二进制大对象,用于存储图片、文件等二进制数据。通常不建议直接存在数据库,而是存文件路径在数据库中,文件本身存在对象存储或文件系统中。

场景 糟糕的选择 推荐的选择 理由
用户状态 VARCHAR(10) TINYINTENUM('active', 'inactive') 数值/枚举比字符串更高效
文章标题 TEXT VARCHAR(200) 合理设置长度,避免TEXT开销
金额 FLOAT/DOUBLE DECIMAL(10, 2) 保证精度,避免计算误差
创建时间 VARCHAR(20) TIMESTAMPDATETIME 专用类型,支持日期计算和排序
性别 VARCHAR(1) ENUM('M', 'F')TINYINT(1) 空间更小,语义更清晰
用户ID(预计千万级) BIGINT INT UNSIGNED INT UNSIGNED范围达42亿,足够且节省4字节
相关推荐
Full Stack Developme14 分钟前
Redis 可以实现哪些业务功能
数据库·redis·缓存
rgeshfgreh31 分钟前
Spring事务传播机制深度解析
java·前端·数据库
无名-CODING32 分钟前
Java Spring 事务管理深度指南
java·数据库·spring
想唱rap38 分钟前
MYSQL在ubuntu下的安装
linux·数据库·mysql·ubuntu
蕨蕨学AI39 分钟前
【Wolfram语言】45.2 真实数据集
java·数据库
The Sheep 20231 小时前
MongoDB与.Net6
数据库·mongodb
BryceBorder1 小时前
SCAU--数据库
数据库·oracle·dba
有味道的男人1 小时前
京东关键词API接口获取
数据库
罗光记1 小时前
《人工智能安全治理研究报告(2025年)发布
数据库·其他·百度·新浪微博
202321336054 刘2 小时前
Linux常用命令分类整理
linux·运维·数据库