数据库设计原则

目录

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

好处

一、数值类型

[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字节
相关推荐
曹牧3 小时前
oracle:NOT IN
数据库·oracle
爬山算法4 小时前
Redis(66)Redis如何实现分布式锁?
数据库·redis·分布式
Super Rookie4 小时前
MongoDB 自动化脚本安装方案
数据库·mongodb·自动化
Code哈哈笑4 小时前
【MongoDB 基本语法】数据库和集合的基本操作--探秘 MongoDB
数据库·mongodb
恋红尘5 小时前
Redis面试八股
数据库·redis·面试
直有两条腿6 小时前
【数据迁移】HBase Bulkload批量加载原理
大数据·数据库·hbase
言之。6 小时前
ClickHouse 数据更新策略深度解析:突变操作与最佳实践
服务器·数据库·clickhouse
白衣鸽子7 小时前
数据库高可用设计的灵魂抉择:CAP权衡
数据库·后端
DokiDoki之父8 小时前
Mybatis—入门 & (配置)SQL提示和日志输出
数据库·sql·mybatis