三范式设计
一般来说,进行表设计的时候,应当遵循三范式:
- 第一范式:保证每列的原子性,例如:地址列还可以细分为国家、省、市、区等
- 第二范式:保证一张表只描述一件事情,例如:学生表里存储的是学生的基础信息,包括姓名,年龄,地址啥的
- 第三范式:通过外键把表功能拆分的更加彻底,例如:学生表里存储的是学生的基础信息,地址应当另外建表,通过外键id关联
反范式设计
因为数据库查询的频率远远的高于修改的频率,为了更好书写sql,会添加一些冗余的字段。
实体关系
通过外键使得表之间要有清晰的实体关系,这样表会比较清晰
- 一对一关系
- 一对多关系
- 多对多关系
主键设计
使用代理主键,而不使用自然主键
- 代理主键指的是自增id
- 自然主键指的的是类似身份证号码,不然软删除的时候,再创建就会主键已经存在导致创建不了等诸多的问题
字段类型
字段的选择,在数据量不大的时候,没什么影响,但是数据量一大可能就是瓶颈所在,应该秉持处理速度快并且节省空间的原则选择字段。
选择优先级:
- 数字类型,也就是整数和小数,因为计算机处理数字比较简单
- 日期类型和二进制类型,处理速度也挺快的,存储空间也是定量的
- 字符串类型,如非万不得已,我们才选择字符串类型保存数据
整数类型
列类型 | 存储空间 | singned | unsigned |
---|---|---|---|
tinyint | 1字节 | -128~127 | 0~255 |
smallint | 2字节 | -32768~32767 | 0~65535 |
mediumint | 3字节 | -8388686~8388607 | 0~16777215 |
int | 4字节 | -2147483848~2147483847 | 0~4294967295 |
bigint | 8字节 | 知道很大就够了 | 知道很大就够了 |
实数类型
列类型 | 存储空间 | 是否精确类型 |
---|---|---|
float | 4字节 | 否 |
double | 8字节 | 否 |
decimal | 每4个字节存9个数字,小数点占一个字节 | 是 |
例如,decimal(18,9)占用9个字节,财务数据一定要用decimal
varchar
varchar是变体长度,根据实际内容保存数据,但是需要注意的是:
- 使用最小的符合需求的长度
- varchar(255),及255以下使用额外1个字节保存长度
- varchar(255)以上使用额外2个字节保存长度,而外长度增加了
- varchar在内存中是定长的,也就是说varchar(5)和varchar(200)占用内存不一样,varchar(5)内存中需要5个字节,varchar(200)内存中需要200字节,内存比较稀缺,设计时候需要注意
- varchar变更长度的时候会出现锁表,这个在mysql5.5以上得到改善,但是当字节从255以下改成255以上,因为额外字节从1个字节变成了2个字节,所以还是会出现锁表,所以要尽量减少线上变更数据库结构的可能
使用场景:
- 适用于存储长度波动大的数据,比如博客文章
- 字符串很少被更新的场景,因为每次修改,都需要重新计算存储空间和保存长度
- 适合保存多字节字符,例如utf-8的中文字符
- 查询速度也会比较慢,因为要先查长度,然后再根据该长度,查出指定字符串的长度
char类型
char属于定长的数据
- char最长长度255
- char类型会自动删除末尾的空格
- char检索和写的效率比varchar高,因为char的每个字符的长度是固定的,比较好计算
使用场景:
- 适合存储长度波动不大的数据,如MD5摘要
- 适合存储短字符串
- 适合存储经常更新的字符串
datetime日期类型
- datetime日期时间类型,固定占用8个字节
- 与时区无关,数据库底层对时区配置是无效的
- 可以保存到毫秒级别的数据
- 可保存的时间范围很大,基本上我们能够遇到的时间范围都能保存
注意:不要使用字符串保存日期类型,这样无法使用mysql自带的日期函数进行操作,检索慢。
mysql中还有date类型和time类型,和datetime类型很相似,开发时候用的很少了解一下即可,区别是,这两个类型只保存datetime类型的部分数据,分别对应:
- date类型,对应datetime类型的,date部分
- time类型,对应datetime类型的,time部分
timestamp时间戳
- 占用4个字节,因为字节比较少,所以时间范围固定1970-01-01到2038-01-19,如果超出这个范围就必须用datetime
- 精确到秒
- 采用整型存储,虽然以日期形式展现,但是底部是以整型来存储
- 依赖于时区,会随着mysql的时区配置,发生变化
- 自动更新timestamp列的值,例如创建的时候,如果没设置字段的值,会自动更新设置为当前的时间戳,有时候还挺方便的