码迷,mamicode.com
首页 > 数据库 > 详细

数据库规范

时间:2020-07-20 13:04:34      阅读:72      评论:0      收藏:0      [点我收藏+]

标签:存储引擎   config   like条件   状态   建表   需要   ica   上线   model   

以下所有规范会按照【高危】、【强制】、【建议】三个级别进行标注,遵守优先级从高到低。

 

一、MySQL数据库设计规范

 1.1

【建议】名称尽量简洁明义,能够一眼看出来这个数据库是用来做什么的,库名与应用的名称尽量一直;

【强制】使用名词作为数据库名称,并且只用英文,不用中文拼音;

【强制】如果有多个单词,则使用下划线隔开,不建义驼峰命名,采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线‘_‘组成;

【强制】创建数据库时必须显式指定字符集,并且字符集只能是utf8mb4

  除非是备份数据库可以加0-9的自然数:db_20151210;

 

1.2

【强制】创建表时必须显式指定字符集为utf8mb4。

【建议】创建表时必须显式指定表存储引擎类型,如无特殊需求,一律为InnoDB。当需要使用除InnoDB/MyISAM/Memory以外的存储引擎时,必须通过DBA审核才能在生产环境中使用。因为Innodb表支持事务、行锁、宕机恢复、MVCC等关系型数据库重要特性,为业界使用最多的MySQL存储引擎。而这是其他大多数存储引擎不具备的,因此首推InnoDB。

【强制】所有的表都必须有备注,写明白这个表中存放的数据内容;

【建议】预估表数据量,如果数据量较大(超过500w行或者单表容量超过 2GB)则需要考虑分表策略。可以等量均衡分表或根据业务规则分表均可。(如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表)

【强制】 一对多,多多的情况下尽量采取A_B=A_B

【强制】建表必须有comment

【强制】建表时关于主键:(1)强制要求主键为id,类型bigint,且为auto_increment

(2)标识表里每一行主体的字段不要设为主键,建议设为其他字段如user_id,order_id等,并建立unique key索引(可参考cdb.teacher表设计)。因为如果设为主键且主键值为随机插入,则会导致innodb内部page分裂和大量随机I/O,性能下降。

【强制】表必备有行数据的主键id, 创建时间字段created_at和最后更新时间字段updated_at,便于查问题。

【强制】拆分大字段和访问频率低的字段,分离冷热数据。

【强制】禁止在数据库中存储图片、文件等大数据,禁止使用外键。(在业务层实现)。

【强制】对于超过 100W 行的大表进行 alter table,必须在业务低峰期执行。因为 alter table 会产生表锁,期间阻塞对于该表的所有写入,对于业务可能会产生极大影响。

 

1.3字段

【强制】没有空格,使用下划线代替,名称中没有数字,只有英文字母。

【强制】避免使用与表名相同的字段名,这会在编写查询时造成混淆。

【建议】尽可能选择短的或一两个单词。

【强制】字段应当有注释,描述该字段的用途及可能存储的内容,如枚举值则建议将该字段中使用的内容都定义出来;

【建议】表与表之间的相关联字段名称要求尽可能的相同;

【高危】库、表、字段需注意:

命名简洁明确要能做到见名识意,(长度不能超过32个字符);只能使用字母、数字和下划线,一律小写

所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)

如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。

表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

以上表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字,字段名称需要慎重考虑。

正例:getter_admin,task_config,level3_name

反例:GetterAdmin,taskConfig,level_3_name

禁止在线上做数据库压力测试

禁止从开发环境,测试环境直接连接生产环境数据库

 

1.4字段数据类型优化

【强制】表达是与否概念的字段,必须使用

_xxx 的方式命名,数据类型是 unsigned tinyint ( 1表示是,0表示否)。 说明:任何字段如果为非负数,必须是 unsigned。必须加上类型注释

【强制】禁止在数据库中存储明文密码。

【建议】小数类型为 decimal,禁止使用 float 和 double。

说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。

【建议】对表里的blob、text等大字段,垂直拆分到其他表里,仅在需要读这些对象的时候才去select。

【建议】文本数据尽量用varchar存储。因为varchar是变长存储,比char更省空间。MySQL server层规定一行所有文本最多存65535字节,因此在utf8字符集下最多存21844个字符,超过会自动转换为mediumtext字段。而text在utf8字符集下最多存21844个字符,mediumtext最多存2^24/3个字符,longtext最多存2^32个字符。一般建议用varchar类型,字符数不要超过2700。

【建议】能使用tinyint就不要使用smallint,int;

【建议】时间类型尽量选取timestamp。因为datetime占用8字节,timestamp仅占用4字节,但是范围为1970-01-01 00:00:01到2038-01-01 00:00:00。更为高阶的方法,选用int来存储时间,使用SQL函数unix_timestamp()和from_unixtime()来进行转换

【强制】varchar,char,text默认NULL值。

【建议】使用varbinary存储大小写敏感的变长字符串或二进制内容。

【建议】表中所有字段必须都是NOT NULL属性,业务可以根据需要定义DEFAULT值。必须要有默认值。(TEXT可为空)。因为使用NULL值会存在每一行都会占用额外存储空间、数据迁移容易出错、聚合函数计算结果偏差等问题。索引NULL列需要额外的空间来保存,所以要占用更多的空间,进行比较和计算时要对NULL值做特别的处理

详细存储大小参考下图:

 

 

 

 

仅供参考

1.5 索引设计

【强制】InnoDB表必须主键为id int/bigint auto_increment,且主键值禁止被更新。

【强制】索引名必须全部使用小写。

【强制】唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。uk_ 即 unique key; idx_ 即 index 的简称,一律使用小写格式,以表名/字段的名称或缩写作为后缀。

【建议】单个表上的索引个数和单个索引中的字段不能超过 5 个。

【强制】不在低基数列上建立索引,例如“性别”,禁止冗余索引和重复索引。

强制】InnoDB 和 MyISAM 存储引擎表,索引类型必须为 BTREE;MEMORY 表可以根据需要选择 HASH 或者 BTREE 类型索引。

【强制】单个索引中每个索引记录的长度不能超过 64KB。

【建议】在建立索引时,多考虑建立联合索引,并把区分度最高的字段放在最前面。如列 user_id 的区分度可由 select count(distinct user_id) 计算出来。

【建议】在多表 join 的 SQL 里,保证被驱动表的连接列上有索引,这样 join 执行效率最高。

【建议】建表或加索引时,保证表里互相不存在冗余索引。对于 MySQL 来说,如果表里已经存在 key(a, b),则 key(a) 为冗余索引,需要删除。

【建议】如果选择性超过 20%,那么全表扫描比使用索引性能更优,即没有设置索引的必要。

【建议】合理创建联合索引(a,b,c) 相当于(a) 、(a,b) 、(a,b,c)都创建了索引。合理使用覆盖索引减少IO,避免排序。

【建议】不在索引列进行数学运算和函数运算,不使用%前导的查询,如 like ‘?‘ 无法使用索引,不使用负向查询,如not in/not like无法使用索引,导致全表扫描。

【建议】select、update、delete语句的where条件列,group by、order by、distinct的字段需要索引。

联表查询时,JOIN列的数据类型必须相同,并且要建立索引,多表JOIN的字段需要索引。

【建议】不在索引列进行数学运算和函数运算,不使用%前导的查询,如 like ‘?‘ 无法使用索引,不使用负向查询,如not in/not like无法使用索引,导致全表扫描。

【建议】建表或加索引时,保证表里互相不存在冗余索引。对于MySQL来说,如果表里已经存在key(a,b),则key(a)为冗余索引,需要删除。

 

1.6分库分表、分区表

【强制】分区表的分区字段(partition-key)必须有索引,或者是组合索引的首列。

【强制】单个分区表中的分区(包括子分区)个数不能超过1024。

【强制】上线前RD或者DBA必须指定分区表的创建、清理策略。

【强制】访问分区表的SQL必须包含分区键。

【建议】单个分区文件不超过2G,总大小不超过50G。建议总分区数不超过20个。

【强制】对于分区表执行alter table操作,必须在业务低峰期执行。

【强制】采用分库策略的,库的数量不能超过1024

【强制】采用分表策略的,表的数量不能超过4096

【建议】单个分表不超过500W行,ibd文件大小不超过2G,这样才能让数据分布式变得性能更佳。

【建议】水平分表尽量用取模方式,日志、报表类数据建议采用日期进行分表。

 

 

二、SQL编写

尽量不要使用sql原生,使用框架自带DB

 2.1 DML语句

【强制】SELECT语句必须指定具体字段名称,禁止写成*。因为select *会将不该读的数据也从MySQL里读出来,造成网卡压力。且表字段一旦更新,但model层没有来得及更新的话,系统会报错。

【强制】insert语句指定具体字段名称,不要写成insert into t1 values(…),道理同上。

【建议】insert into…values(XX),(XX),(XX)…。这里XX的值不要超过5000个。值过多虽然上线很很快,但会引起主从同步延迟。

【建议】SELECT语句不要使用UNION,推荐使用UNION ALL,并且UNION子句个数限制在5个以内。因为union all不需要去重,节省数据库资源,提高性能。

【建议】in值列表限制在500以内。例如select… where userid in(….500个以内…),这么做是为了减少底层扫描,减轻数据库压力从而加速查询。

【建议】事务里批量更新数据需要控制数量,进行必要的sleep,做到少量多次。

【强制】事务涉及的表必须全部是innodb表。否则一旦失败不会全部回滚,且易造成主从库同步终端。

【强制】写入和事务发往主库,只读SQL发往从库。

【强制】除静态表或小表(100行以内),DML语句必须有where条件,且使用索引查找。

【强制】生产环境禁止使用hint,如sql_no_cache,force index,ignore key,straight join等。因为hint是用来强制SQL按照某个执行计划来执行,但随着数据量变化我们无法保证自己当初的预判是正确的,因此我们要相信MySQL优化器!

【强制】where条件里等号左右字段类型必须一致,否则无法利用索引。

【建议】SELECT|UPDATE|DELETE|REPLACE要有WHERE子句,且WHERE子句的条件必需使用索引查找。

【强制】生产数据库中强烈不推荐大表上发生全表扫描,但对于100行以下的静态表可以全表扫描。查询数据量不要超过表行数的25%,否则不会利用索引。

【强制】WHERE 子句中禁止只使用全模糊的LIKE条件进行查找,必须有其他等值或范围查询条件,否则无法利用索引。

【建议】索引列不要使用函数或表达式,否则无法利用索引。如where length(name)=‘Admin‘或where user_id+2=10023。

【建议】减少使用or语句,可将or语句优化为union,然后在各个where条件上建立索引。如where a=1 or b=2优化为where a=1… union …where b=2, key(a),key(b)。

【建议】分页查询,当limit起点较高时,可先用过滤条件进行过滤。如select a,b,c from t1 limit 10000,20;优化为: select a,b,c from t1 where id>10000 limit 20;。

2.2 多表连接

【强制】禁止跨db的join语句。因为这样可以减少模块间耦合,为数据库拆分奠定坚实基础。

【强制】禁止在业务的更新类SQL语句中使用join,比如update t1 join t2…。

【建议】不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用join来代替子查询。

【建议】线上环境,多表join不要超过3个表。

【建议】多表连接查询推荐使用别名,且SELECT列表中要用别名引用字段,数据库.表格式,如select a from db1.table1 alias1 where …。

【建议】在多表join中,尽量选取结果集较小的表作为驱动表,来join其他表。

2.3 事务

【建议】事务中INSERT|UPDATE|DELETE|REPLACE语句操作的行数控制在2000以内,以及WHERE子句中IN列表的传参个数控制在500以内。

【建议】批量操作数据时,需要控制事务处理间隔时间,进行必要的sleep,一般建议值5-10秒。

【建议】对于有auto_increment属性字段的表的插入操作,并发需要控制在200以内。

【强制】程序设计必须考虑“数据库事务隔离级别”带来的影响,包括脏读、不可重复读和幻读。线上建议事务隔离级别为repeatable-read。

【建议】事务里包含SQL不超过5个(支付业务除外)。因为过长的事务会导致锁数据较久,MySQL内部缓存、连接消耗过多等雪崩问题。

【建议】事务里更新语句尽量基于主键或unique key,如update … where id=XX; 否则会产生间隙锁,内部扩大锁定范围,导致系统性能下降,产生死锁。

【建议】尽量把一些典型外部调用移出事务,如调用webservice,访问文件存储等,从而避免事务过长。

【建议】对于MySQL主从延迟严格敏感的select语句,请开启事务强制访问主库。

2.4 排序和分组

【建议】减少使用order by,和业务沟通能不排序就不排序,或将排序放到程序端去做。order by、group by、distinct这些语句较为耗费CPU,数据库的CPU资源是极其宝贵的。

【建议】order by、group by、distinct这些SQL尽量利用索引直接检索出排序好的数据。如where a=1 order by可以利用key(a,b)。

【建议】包含了order by、group by、distinct这些查询的语句,where条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

2.5 线上禁止使用的SQL语句

【高危】禁用update|delete t1 … where a=XX limit XX; 这种带limit的更新语句。因为会导致主从不一致,导致数据错乱。建议加上order by PK。

【高危】禁止使用关联子查询,如update t1 set … where name in(select name from user where…);效率极其低下。

【强制】禁用procedure、function、trigger、views、event、外键约束。因为他们消耗数据库资源,降低数据库实例可扩展性。推荐都在程序端实现。

【强制】禁用insert into …on duplicate key update…在高并发环境下,会造成主从不一致。

【强制】禁止联表更新语句,如update t1,t2 where t1.id=t2.id…。

数据库规范

标签:存储引擎   config   like条件   状态   建表   需要   ica   上线   model   

原文地址:https://www.cnblogs.com/laowangbk/p/13344330.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!