58到家数据库30条军规解读&个人理解

2018-03-07 20:09:58 Linux 阅读 (6001) 评论(0)

  我们程序员在面试找工作中,经常会被问到数据库设计这块的能力,因为数据库设计更多的是考察一个开发者“自上而下”的一种综合能力,这里给一个知乎上的问答很多 IT 招聘要求中需要优秀的数据库设计能力。什么是「数据库设计能力」?,大家可以了解一下。下面就介绍一下数据库设计时应该遵循的规范。

一、基础规范


(1)必须使用InnoDb存储引擎

    读:InnoDB存储引擎支持事务,行级锁,并发性能更好,CPU及内存缓存页优化使得资源利用率更高。Myisam在现在的开发中逐渐被废弃不再使用,myisam存储引擎虽然在查询操作更快,但是现在开发中各级缓存cache的加入使得即使是innodb引擎的查询操作效率也很高,而在事务处理,数据安全性方面,myisam可以说是“一无是处”。


    (2)必须使用utf8字符集

    解读:utf8编码可以说是各个编程语言中默认采用的字符集编码,包含世界上所有的字符和符号,不用转码操作,而且它是可变字节的,节省空间。但是在国内一些很古老的项目还是采用gbk或gb2312(捉急)。


    (3)数据表(字段)写上中文注释

    解读:因为很久之后可能自己都能忘了当时自己设计的字段是啥意思了

        

    (4)禁止使用存储过程,视图,触发器,Event

    解读:高并发大数据的互联网业务,架构设计思路是“解放数据库CPU,将计算转移到服务层”,并发量很大的情况下,这些功能极有可能将数据库拖死。业务逻辑放到服务层具备更好的扩展性,能够轻易实现“增机器就加性能”。数据库擅长数据的存储与索引,CPU计算还是上移吧。

        

    (5)禁止存储大文件或者大照片

    解读:虽然数据库可以存储数据量很大的二进制数据,但是这样会耗费很大的系统资源。不如把图片等静态资源存储到服务器文件系统中,数据库存储期url。


    二、命名规范


    (6)只允许内网域名,而不是ip连接数据库


    (7)线上环境,开发环境,测试环境数据库内网域名遵循命名规范


    (8)数据库名,表名,字段名全用小写字母+下划线,长度不超过32个字符,必须见名知意,禁止拼音英文混用。不建议过度设计,例如,一个goods表的自增id,商品名字,商品价格等,字段名应为id,name,price,而没必要设计成goods_id,goods_name,goods_price,这个表已经是goods表,当然会存储与商品相关的信息,再加上goods_,显得“画蛇添足”,过度设计了。


    (9)表名t_xxx,非唯一索引名idx_xxx.唯一索引名uniq_xxx


    三、表设计规范


    (10)单个项目数据表数目必须小于500个


    (11)单个数据表字段数必须小于30个


    (12)表必须有主键,例如自增主键

    解读:

       a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用

       b)主键要选择较短的数据类型,Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

       c)无主键的表数据删除时,在row模式的主从架构,会导致备库夯住


    (13)禁止使用外键,如果有外键完整性约束,需要应用程序控制

    解读:外键会导致表与表之间的耦合,update和delete操作都会涉及到相关联的表,十分影响sql的性能,甚至会导致死锁。高并发情况下容易造成数据库性能的下降,大数据高并发场景下的数据库使用以性能为优先


    四、字段设计规范

    

(14)必须把字段定义为NOT NULL并且提供默认值

解读:

  a)null的列使索引,索引统计,值比较都更加复杂,对MySQL来说更难优化

  b)null这种类型MySQL内部需要进行特殊处理,增加数据库处理数据的复杂性;同等条件下,表中有较多空字段的时候,数据库的性能会下降很多

  c)null值需要更多的存储空间,无论是表还是索引中每行的null的列都需要额外的空间来标识

  d)对null的处理,只能采用is null或is not null,而不能采用=,in,

    

(15)禁止使用TEXT,blob类型

解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能。

  

(16)禁止使用小数存储货币

解读:几乎所有的编程语言在处理小数时,都会或多或少出现丢失精度的问题。所以,如果以分为单位时。可以把货币乘以100存进数据库

    

(17)必须使用varchar存储手机号(电话号)

解读:

 a)涉及到区号或国家代号,可能出现+-()等字符

 b)不会有人拿手机号去做数学计算的

 c)varchar支持模糊查询,如:like “139%”

    

(18)禁止使用enum枚举类型,可以使用TINYINT代替

解读:

  a)增加新的enum值就要做DDL操作

  b)enum的内部实际存储就是整数,你以为自己定义的是字符串吗?

五、索引设计规范

19)单表索引建议控制在5个以内

 

20)单索引字段数不允许超过5

解读:字段超过5个时,实际已经起不到有效过滤数据的作用了

 

21)禁止在更新十分频繁、区分度不高的属性上建立索引

解读:

       a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能

       b)“性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似

 

22)建立组合索引,必须把区分度高的字段放在前面

解读:能够更加有效的过滤数据

 

六、SQL使用规范

23)禁止使用SELECT *,只获取必要的字段,需要显示说明列属性

解读:

   a)读取不需要的列会增加CPUIONET消耗

   b)不能有效的利用覆盖索引

   c)使用SELECT *容易在增加或者删除字段后出现程序BUG

 

24)禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性

解读:容易在增加或者删除字段后出现程序BUG

 

25)禁止使用属性隐式转换

 

26)禁止在WHERE条件的属性上使用函数或者表达式

解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描

正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')

 

27)禁止负向查询,以及%开头的模糊查询

解读:

          a)负向查询条件:NOT!=<>!<!>NOT INNOT LIKE等,会导致全表扫描

            b%开头的模糊查询,会导致全表扫描

 

28)禁止大表使用JOIN查询,禁止大表使用子查询

 解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能

 

29)禁止使用OR条件,必须改为IN查询

解读:旧版本MysqlOR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮助实施查询优化呢?

 

30)应用程序必须捕获SQL异常,并有相应处理







                                    原文转自http://mp.weixin.qq.com/s/Yjh_fPgrjuhhOZyVtRQ-SA


评论