Skip to content

SQL style guides

雷霹雳的爸爸 edited this page Aug 6, 2018 · 5 revisions

关系数据库使用设计风格指南

参考

  1. 阿里巴巴开发手册1.4.0版
  2. SQL style guide
  3. SQL style guide misconceptions
  4. Is there a naming convention for MySQL?
  5. SQL Antipartterns

内容

以阿里的开发手册1.4版(以下简称手册)中的MySQL部分为蓝本及基础,并结合:

  • 业务特点
  • 组织级设计风格约定

而最终形成的文本

如果遵循阿里开发手册中的意见(page25-30),这里不再特别列出,以下,仅记录对手册的修改和补充部分

手册中内容的调整

第(一)3项,关于表名的命名形式

原文:

【强制】表名不使用复数名词。

扩充内容,修改为:

  • 【强制】表名不使用复数名词
  • 同时【建议】使用集合类名词来作为复数形式
  • 一个例子是用staff代替employee

说明:

  • 表名单数还是复数是个由来已久的设计抉择
  • 这个问题从根源上看,表是关系模式的一个现实表达,严格地说是元组的集合,因此复数名词并不糟糕
  • 但通常习惯性禁止复数形式的理由是:工具和面向对象:
    • 复数单词形式和程序代码中类的名字习惯是不一致的,不利于持久层框架工具的转换,必然需要额外的注解或配置文件来处理这个问题
  • 因此考虑实用性,强制不用复数名词是有现实性基础的,但最好考虑关系模型中的本意,一个好的关系模型不该被面向对象设计干扰

第(一)9项,关于主键的设计和必备字段

原文:

【强制】表必备三字段:id, gmt_create, gmt_modified。 说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。gmt_create,gmt_modified 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被动更新。

修改为:

  • 【建议】表必备三字段:xxx_id或id, created_gmt_at, updated_gmt_at
  • 如果确定没有性能问题,【建议】使用自然键做为主键
  • 如果基于效率问题考虑设置代理键(或称伪主键,即 surrogate key 或 pseudokey ),应该使用 bigint unsigned,单表时自增、步长为1
  • 如果生成类似操作日志表的主键或分片存储数据,【建议】使用类似 snow flake 算法保证全局唯一,导引参考
  • 如果不确定是否有效率问题,使用代理键
  • 主键字段命名首选使用_id后缀,和能反映表对应实体(如果有)的类型的名字,比如如果是缺陷表,就叫bug_id,除非遗留系统中,无需修改原名称(具体参考知名产品wordpress的混乱现状
  • 手册中的gmt是提示性的,值得吸纳,表示这里实际上存储的应该是与时区无关的时间戳,所以应当保留,但是两个语态解释太烂了,分明这里应该是时态表达是重点,固化在数据库中值的必然都是过去式,操作主体都该是应用程序,(current_timestamp_似乎不支持datetime,或者支持也有时区设置问题的潜在问题和这里gmt设计相悖

说明:

  • 从性能角度,认为手册对 id 设计的规定虽然是有效的;
  • 但从业务上,认为是武断的
  • unsigned bigint毫无疑问有着更好的磁盘内存的存储效率;但自然键更符合业务本意,且不一定会造成性能问题
  • 命名这里为什么建议使用了蓝精灵命名法,这来自于SQL反模式作者的定义,因为
  • 手册中gmt的强调

手册内容的补充

通用规则

  • 【强制】表名、字段名限定在50个字符以内(通常是30个字符,但考虑鼓励更准确的命名,放宽)
  • 【建议】表的列数控制在50个字段以下,特殊场景可放宽;text等大字段要考虑垂直分表
  • 【强制】要求每个字段都有注释说明清楚业务含义
    • 由于不做数据库范式的强制性要求,因此允许不使用参照表来限定枚举类的值,即可以用整型表示枚举值的情况,这时需要在注释中明确记录0,1,2,...分别都表达的具体含义
  • 持久层框架的选择
    • 【强制】不要直接使用hibernate
    • 【强制】一个project中,只选用一种持久层框架
    • 【建议】首选JPA、少用 HQL;次选Mybatis;尽量不用Spring JdbcTemplate;可以使用jooq等DSL风格框架;唯一必须要遵从的就是上一条规则,一个project中只选用一种持久层框架
  • 【强制】SQL语句中关键字使用大写

MySQL

  • 【强制】不修改全局缺省的数据库隔离级别
  • 【建议】显式的为每个事务声明事务隔离级别
  • 【建议】创建表语句显式声明数据库引擎,推荐使用缺省的InnoDB引擎,如有特别的需要其他引擎,注释说明清楚

微服务语境下设计风格约束

  • 【建议】微服务设计不要使用共享数据库模式,而以Database per Service为主
  • 【建议】当使用数据库每服务模式时,出于效率考虑,允许冗余存储其他库的数据,但字段规格应当与业务主库中的定义保持一致,同时注意上述枚举整型值的注释保持一致的更新

Clone this wiki locally