数据库规范
- 表使用 InnoDB 引擎,字符集统一为utf8mb4,原因: InnoDB支持事务和行级锁,utf8mb4兼容性比utf8更好。
- 库名、表名由小写字母、数字组成,下划线分隔。
- 表必须定义使用自增长作为主键,命名为 id,类型bigin。原因:如果使用uuid或者随机id做主键,容易引起页分裂,导致性能问题。最佳实践详情:数据库设计规范(MySQL第一版)-主键定义最佳实践
- 表必须包含创建时间
- 示例:
- dbctime DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) comment '创建时间',
- dbutime DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) comment '更新时间'
- 禁止使用外键、触发器、存储过程、视图等非标准化语法。如果是第三方或者外部系统数据库,
- 表和字段需要有注释,注明用途,散列值必须定义每一个值的业务含义。范围值必须明确取值范围。
- 禁止使用 enum(枚举)类型。原因: mysql 虽然对于enum底层使用了bit类型,但是计算和处理方式有很多问题,尤其是扩充字段值空间的时候。
- 不允许字段可以为 null,原则上不允许设置默认值,如若要设置,默认值必须没有业务逻辑含义。原因:1、mysql 对null值有很多特殊处理,性能差,而且判断容易出现逻辑问题。如判断是否为null,null值导致索引失效等。补充说明:新增字段必须经过两次DDL,一次默认值有业务含义,改表完成后去除默认值或改为无业务含义默认值。
- 不允许存储text、blob字段族(包括超过8069字节数的varchar),若一定要有,必须单表存储。建议使用oss存储。原因:1、text、blob字段mysql innoDB引擎会单独存储,不会放到索引组织表(聚簇索引)上,并不能带来单次IO的性能优势。2、会占据大量的磁盘和网络IO,引发满响应,满响应会消耗数据库和应用服务处理资源,非常危险。3、超过8096字节数的varchar 会被当做text 处理。4、一段时间内我们没办法完全避免和清除select * 这种不规范操作。
- 存储text或blob的表命名以 【主表表名】+【_text】 或 【_blob】命名,以方便后续code_review。
- 单表不允许超过5个索引,每个索引不超过3个字段。原因:1、索引空间大小(索引占用的内存大小,或内存中能存下的索引数量)至关重要,复杂索引会降低索引空间效率,甚至索引数据回盘。2、mysql 并发控制的主要对象是索引数据,过多过复杂的索引会大幅度降低写入和更新效率,导致数据库性能大幅度下降:索引空间内存计算:select sum(INDEX_LENGTH) from `information_schema`.`TABLES`
- 不允许在超过长度为10的字符字段上建立索引。原因,同上,外加字符串比较本质是循环字符比较,非常低效。最佳实践是为字符串字段建立hash值,在hash值上建立索引。请考虑hash算法的碰撞率和计算效率,可以使用google murmur hash3
- 金额数据存储使用整形或decimal型存储,建议是前者,禁止使用float 或者double。原因: float和double为浮点类型,数据并不精确。
- 禁止使用like 模糊查询。原因:错误使用like 查询容易引发雪崩,直接一刀切。