数据库规范


强制要求:

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

进阶要求:

  1. 单表字段数不能超过35,或单条数据尽量不超过磁盘页大小。原因:存取效率。
  2. 联合索引,区分度高的字段在前,区分度低字段在后。原因:最左原则,提升运行效率
  3. 索引字段不允许更新。原因:索引分裂带来的效率和稳定性问题。
  4. 不允许select*。原因:一是强化需求语义,符合迪米特法则,避免字段增删带来的系统故障。二是考虑节省无关的IO性能和传输性能。