一、命名
可读性要高:字段名,表名必须英文,不要缩写,选用合适的单词,避免出现歧义,名称不必过长,范围内起到标识即可。
规范统一:字段名,表名不用复数名词,统一小写字母,不能数字开头
表名:业务名称_表的作用
索引命名:主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名
二、字段类型
数字:
-
尽可能选择存储空间小的字段类型,从tinyint、smallint、int、bigint从左往右开始选择。
-
如果非负的整型数字,最好加上 unsigned,尤其是id这种自增主键时 。
-
小数类型如金额,则选择 decimal,禁止使用 float 和 double,否则会不精确。
时间
- timestamp:全球统一时间,表示的时间戳值,默认到秒级别,如果需要更精确毫秒,可以下面这样:
-- TIMESTAMP 后面的3 代表时间有3位小数(单位还是秒)
CREATE TABLE test (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
modified_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)
);
-- 插入一条数据
INSERT INTO test (created_at, modified_at) VALUES (DEFAULT, DEFAULT);
-- 查询一下看看
SELECT * FROM test;
-- 查询结果
+----+----------------------------+----------------------------+
| id | created_at | modified_at |
+----+----------------------------+----------------------------+
| 1 | 2021-05-25 15:46:42.523 | 2021-05-25 15:46:42.523 |
+----+----------------------------+----------------------------+
- datetime: 表示的时间范围更大,但是会丢失时区信息。
字符串
-
如果存储的字符串长度几乎相等,使用 char (定长字符串类型),比如身份证号。用char比varchar性能略好一些。
-
varchar是可变长字符串,大部分情况下字符串使用这个类型,后面的长度数字代表字符的长度,不是字节的长度,varchar长度不要超过5000。
-
字符串如果是json,可以用json类型,使用json类型好处是查询语句也可以直接查询json某个字段的值,也可以对json内部的字段加索引。
-
如果存储的值太大,字段类型修改为text,在对性能要求高的情况下,还需单独抽出一张表,用主键与之对应。
-
text能支持的最大长度为65535,超过这个长度会自动截断且不会报错,如果存取的是json,读取的时候反序列化会报错。这个时候可以用mediumtext或者longtext。
枚举
-
枚举可以用数字或者字符串,各有优缺点 ,但是别忘了comment后面注释清楚每个枚举的含义。
三、索引
区分度
-
区分度不高的不适合做索引,但也有特殊情况,比如一个状态,只有有1和2两种值,2是异常状态,比例在0.1%左右,需要定时扫表获取异常状态的数据重新处理,这个时候也可以将该字段加上索引。
-
判断区分度的方式
使用频率
- 使用频率高才有必要加索引
字符串索引
- 一般没必要对全字段建立索引,根据实际文本区分度决定索引长度,区分度判断方法:select count(distinct left(列名, 索引长度))/count(*) from 表名
联合索引
-
最左匹配原则:区分度高的放左边,范围查询或者排序或者分组的放右边。
-
覆盖索引原则:如果能用到覆盖索引的可以加在联合索引里,当然前提字段不多的情况下。
join字段
- join的字段一般要建立索引且字段类型要相同,字段类型不同时join可能会不走索引。
索引个数
-
索引个数一般不要太多,太多影响插入更新的性能,一般不超过5个。
四、其他
主键
- 最好是自增id或者趋向自增的id,否则插入数据可能引起底层页分裂,插入性能会差很多。
编码
- 一般用utf8mb4: 完全兼容utf8,4个字节长度,可以存储emoji表情等特殊字符。
通用字段统一
- 下面字段可以都有且统一命名
is_delete tinyint not null comment '删除标记 0:正常,1:已删除',
creator varchar(64) default '' not null comment '创建人',
updator varchar(64) default '' not null comment '更新人',
create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间',
update_time timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间'
不用外键
- 外键是数据库提供的,因为性能差,不建议使用,实际也很少见人使用。在业务解决这种逻辑。
适当冗余
- 不需要严格遵守 3NF,某些场景通过业务字段冗余来减少表关联。
关于Not null
-
一般建议not null,有一些好处,主要是避免查询时不熟悉null用法,sql写错。
-
某些情况下null 有单独意义,也可以使用null,因为使用了not null,必须指定默认值,而日期,金额这种,某些情况下指定默认值是不太合适的。