数据库设计基本规范

数据库

  • 采用InnoDB引擎,禁用其他类型引擎
  • 采用utf8mb4字符集
  • 只允许访问所属数据库,禁止跨库访问
  • 禁止临时任务表长期存在于数据库中
  • 创建数据库/表的时候,还要对排序规则进行审查:
    • 需要区分特殊字符:默认的general_ci 更快,但是unicode_ci 更准确,utf8mb4_general_ci中S=ß,而utf8mb4_unicode_ci中ss=ß ,这种情况unicode_ci能准确判断(参考:http://mysql.rjweb.org/utf8mb4_collations.html)
    • 大小写敏感:默认的general_ci大小写不敏感,utf8mb4_unicode_ci大小写不敏感,但utf8mb4_bin 大小写敏感

表/列/索引命名

  • 全部采用英文单词小写,单词间下划线分割,禁用拼音
  • 表明中包含的单词采用单数,禁用复数
  • 表名以**业务名称_**开头,
  • 列名以表名**业务名称_xxxxxx**开头,(除了逻辑删除列、创建时间、更新时间和关联其他表的列之外所有属于本表的基本字段都必须遵守)

注:有更新场景,默认增加create_bycreate_timeupdate_byupdate_time字段,没有则默认增加create_time字段,关于create_timeupdate_time 如果有业务需要,要增加xxx_create_timexxx_update_time作为业务只用。

分析:不仅便于理解,更重要的是便于程序编写,设想如果多表联查,有同名字段(比如create_time等),区分的时候就要用别名,如果再作为查询条件的话,程序处理起来更繁琐,需要对同名字段查询的别名进行逻辑校验。

  • 索引命名
    • uniq_ 前缀命名唯一索引
    • idx_ 前缀命名非唯一索引,命名规范:idx_xxxx_xxxx, idx_作为前缀,xxxx为索引包括的列名,索引覆盖字段控制在5个字段以内。
  • 表中每一列,都必须有comment中文注释,废弃的字段,一经废弃立即清除

数值

  • 禁止使用小数(floatdouble)存储币值,均使用整数,以分作为计量单位。
  • 手机号 用char来存储,以便可**like **查询

默认值

  • 所有字段都必须是 NOT NULL
  • 数值的默认值均为0,字符串的默认值为**空字符串''**,禁止 null作为默认值

关于删除

表设计之初,就需要明确是 逻辑删除 还是 物理删除

主外键

  • 任何表都必须要有主键
  • 禁止使用外键,使用程序来管理

禁用项

  • 禁止使用单库自增键来生成ID
  • 禁止使用存储过程
  • 禁止使用视图
  • 禁止使用触发器 (trigger),事件 (event),自定义函数(function),存储过程(procedure),会影响备份恢复,以及数据库拆分。
  • 禁止在sql做到最优化之前,随意添加索引来提升查询性能;

SQL规范

  • 禁止使用**select ***,只获取必要字段
  • 禁止在数据列(特别是索引列)上使用函数,不在sql中做计算,where 条件里 也避免在列上使用函数;
  • 禁止大sql,可拆分成小sql,在业务层拼合数据;
  • 尽量避免使用join连接,特别是大数据表,是在不可避免时不要超过3个,同时大数据表也避免使用子查询
  • 查询时使用小数据集驱动,where条件避免放在最外层,大数据表计算条数时,尽量覆盖索引
  • insert必须指定字段,禁止使用**insert into T values()**
  • order by 规范:排序错误用法 order by column1,column2,column3 desc 这种方式 本质上相当于 order by column1 asc,column2 asc,column3 desc ,并不是3个字段都降序,而且这种排序字段的升降序不一致,即便三个列包含在索引里仍无法使用索引, 正确的方式:**order by column1 desc,column2 desc,column3 desc**
  • 禁止在sql中拼接json字符串,在程序中执行**JSON.parse(),应将json字符串转换为json**对象,此处理方式受记录值包含特殊字符影响,会在转换成json对象时报错,后期维护成本很高。
  • 禁止在where条件列使用函数或者表达式
  • 禁止负向查询以及**%**开头的模糊查询
  • 禁止大表JOIN子查询
  • 禁止 explain 后出现如下情况的SQL语句
1
2
Using filesort
Using temporary