标签:存储引擎 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