MySql设计规范

前言

这是来自一线的实战经验,每一条军规背后都是血淋淋的教训。

核心篇

  • 不在数据库做运算
    存储过程、函数、触发器、试图、级联删除等数据库功能严禁使用。数据库是用来存取数据的,而不是做业务处理的。数据库做集群的代价远远大于应用服务器。在当前这个互联网时代中软件所需要处理的数据越来越多,请珍惜数据库的资源。
  • 控制单表数据量
    一年内单表数据量不要超过500W(随着硬件性能提升而提升);单库不超过50张表,推荐ER图不超过一屏幕,一目了然可以大大提高对数据库结构的理解。
  • 控制单表字段数上限在20~50
    字段少的好处多多:IO高效、全表遍历快、表修复快、alter table 快、提高开发效率
  • 平衡范式与冗余
    本库在没有性能瓶颈的情况下不考虑冗余。跨库关键字段必须冗余,实时类数据要保证最终一致性,(在业务判断影响不大的情况下也可以不同步)当出现频繁的同步需求时,往往是库的拆分出问题了,应该考虑调整数据库设计。历史类数据不叫冗余那是尊重历史,如订单中的客户名称、货品名称等。
  • 拒绝3B
    大SQL、大事务、大批量

字段篇

  • 用好数值字段类型
    在够用的情况下尽量选择字节数少的类型。
    tinyint(1B)、smallint(2B)、mediumint(3B)、int(4B)、bigint(8B)
    float(4B)、double(8)
    decimal(m,d)
  • 能用数字不用字符串
    数字更高效、查询更快(经验值是20%)、占用空间更小。
  • 避免使用null值
    在mysql中无法对null进行查询优化,有null值的列加索引需要额外空间,含null的复合索引无效。设计合理的默认值可以规避null的问题,例如 varchar用 emptystring ,数字用0等等。
  • 禁止使用text/blob/clob等大字段
    这些大字段会强制生成硬盘临时表,浪费空间。在业务需要存储较大内容时,请使用文件服务器存储,在数据库中存储其url地址。
  • 不在数据库里存图片
    原理同上。

索引篇

  • 谨慎合理添加索引
    索引可以提高查询的性能,但会减慢更新的速度。所以并不是越多越好,控制在字段数的20%以内。
  • 字符字段必须建前缀索引
    将整个字符串都加入到索引中,是十分浪费空间的。其实用前若干位已经可以达到很好的效果了,实际用多少位需要根据实际场景判定。这个给大家几个数字作为参考
    单字母区分度:26(字母,不考虑大小写)+ 10(数字)= 36(理论值是255,这里我们只考虑常见的)
    4字母区分度:36 × 36 × 36 × 36 = 1,679,616(1百多万)
    5字母区分度:36 × 36 × 36 × 36 × 36 = 60,466,176(6千万)
    6字母区分度:36 × 36 × 36 × 36 × 36 × 36 = 2,176,782,336(20亿)
  • 不在索引列做运算
    索引失效。其实所有列的运算都不推荐,运算应该交给java。
  • 主键使用bigint且自增
    忌用字符串做主键。
  • 禁止使用外键
    高并发时容易死锁。使用程序保证约束。

Sql篇

  • 尽可能简单
    将一条大sql拆成几条小sql执行。一条大sql可能把整个数据库堵死。简单sql缓存命中率更高、减少锁表时间,用上多cpu(一条sql只能在一个cpu运算)。
  • 保持事务(链接)短小
    事务使用原则:即开即用,用完即关
    与事务无关操作放到事务外面,减少锁资源的占用
    不破坏一致性前提下,使用多个短事务代替长事务
  • 禁止使用select *
    只取需要数据列,减少传输量,减少表变化带来的影响。join时同名列会自动添加后缀影响程序的取数。
  • 用union all 而非 union
    union 的结果是去重的,这个消耗很大。
  • 改写or为in()
    or的效率为 O(n),in的效率为O(Log n)当n很大时,or会慢很多。即便如此也要控制in的个数,建议n小于200。
  • 改写or为union
    前面的是一个字段多个值的场景,这个是不同字段的场景。注意:这里不能使用union all。
  • 避免非逻辑查询和%前缀模糊查询
    非逻辑指 not、!=、<>、!<、!>、not exists、not in、not like等。%前缀模糊查询 使用不了索引,导致全表扫描。
  • 同数据类型的列值比较
    数字对数字,字符对字符。浮点型不推荐比较。主外键必须使用同数据类型(通常是bigint)。不同类型的字段比较时,会消耗类型转换的运算量,并且容易导致索引失效。
  • 禁止单词请求中大批量更新
    容易出现大事务。在设计层面规避,无法避免时请使用队列控制数据库的压力。
  • explain
    使用explain优化sql语句是每个程序员都应该学会的。开发库往往比生成库少很多的数据,一条未经优化的sql上线,可能导致一场灾难。

约定篇

  • 隔离线上线下
  • 禁止使用子查询
    大部分情况很难优化。in 通常是可以改写为join的。
  • 禁止在程序端显示加锁
    外部锁对数据库不可控。高并发时是灾难。极难调试和排查。
  • 统一字符集为UTF-8
    校对规则 utf8_general_ci
  • 统一命名规范
    库、表、字段统一使用小写,单词之间使用下划线分隔。
    主键:表名关键字id
    索引:idx
    字段名(复合组件则用多个字段名,过长时使用缩写)
    避免使用保留字:如 desc 描述的缩写 结果是 排序的关键字。
  • 必备字段
    每张实体表都需要记录以下字段,并置于字段最后面
    create_time
    create_user_id
    create_user_name
    modify_time
    modify_user_id
    modify_user_name
    插入时modify的值同create
    关联表不需要记录
    固定数据的基础资料不需要记录
  • 日期类型统一使用 timestamp
    国际物流是有时区问题的。
  • 字段顺序
    设计表结构时需要按照重要程度自上而下排列,在添加字段时必须严格遵守,不能简单的加载最后面。相关的字段必须排在一起,例如user_id、user_name。
  • 可事先约定且有限值的字段使用varchar
    虽然常见的做法是int或tinyint,但是在意义表达上不如字符串来的清晰,为了更加便于维护,

你可能感兴趣的:(MySql设计规范)