Mysql建表姿势归纳

155 阅读4分钟

一、命名

可读性要高:字段名,表名必须英文,不要缩写,选用合适的单词,避免出现歧义,名称不必过长,范围内起到标识即可。

规范统一:字段名,表名不用复数名词,统一小写字母,不能数字开头

表名:业务名称_表的作用

索引命名:主键索引名为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,必须指定默认值,而日期,金额这种,某些情况下指定默认值是不太合适的。