一、数据库命名规范
1. 所有数据库对象名称必须使用小写字母并用下划线分割
R:Linux系统中是大小写敏感的,若大小写混合使用,则不容易区分
2. 所有数据库对象名称禁止使用Mysql保留关键字
关键字列表,给出一个链接,上面总结的关键字很全面。https://www.cnblogs.com/osfipin/p/4248022.html
3. 数据库对象的命名要能做到见名识意,并且最好不要超过32个字符
Eg:用户账号表可表示为user_account
4. 所有的临时表必须以tmp_为前缀并以日期为后缀
R:为清理临时表提供了方便
5. 备份库,备份表必须以bak_为前缀并以日期为后缀
R:也是为了后面的清理提供了方便
6. 所有存储相同数据的列名和列类型必须一致(关联列)
R:这个是我自己踩过的坑,有一次在设计时没有注意,将同一个变量在一个表中定义为float,另一个表中定义为double,这样在进行处理时会出现问题。
二、数据库基本设计规范
1. 所有表必须使用Innodb存储引擎(只要是Innodb能够满足的)
R:Innodb是5.6以后的默认引擎,支持事务,行级锁,更好的恢复性,高并发下性能更好,更符合一般开发的要求
2. 数据库和表的字符集统计使用UTF8
R:UTF8兼容性更好,几乎可以包括使用的所有字符,不过若只有中文,也可以使用GBK等。统一字符集之后可以避免由于字符集转换产生的乱码。需要注意的是在Mysql中UTF8字符集汉字占3个字节,ASCII占一个字符
3. 所有表和字段都需要添加注释
注释方法是使用comment从句添加表和列的备注
R:一般公司的是大型项目,为以后其他人的维护和更新提供了方便。
4. 尽量控制单表数据量的大小,建议控制在500万以内
解决办法:历史归档,分库分档,物理分表,逻辑分表
5. 尽量做到冷热数据分离,减小表的宽度
R:把经常一起使用的列放在一个表中,对select*会更友好
6. 禁止在表中建立预留字段
R:无法确认存储的数据类型,无法选择合适的类型,并且以后修改的成本大于增加一个字段的成本,所以没有必要。
7. 禁止在数据库中存储图片,文件等二进制数据
R:一般图片和文件数据会很大,存储过多,会影响数据库的性能
解决办法:在专门的文件服务器上存储图片和文件,在数据库中存储对应的地址信息
8. 禁止在线上做数据库压力测试
R:会产生大量垃圾数据
9. 禁止从开发环境,测试环境直连生产环境数据库
三、索引设计规范
1. 限制每张表上的索引数量,建议单张表索引不超过5个
R:索引可以增加查询效率,但同样会降低插入和更新效率
2. 禁止给表中的每一列都建立单独的索引
R:数据存储的逻辑顺序和索引的顺序是相同的,Innodb是按主键的顺序来组织表的,所以每个Innodb表必须有一个主键(唯一且非空)
*主键的选择:
①不使用更新频繁的列作为主键,不使用多列主键
②不使用UUID,MD5,HASH,字符串列作为主键(不能保证递增)
③建议选择使用自增ID值
3. 常见索引列建议:(在哪些列上建立索引)
①Select,update,delete语句的where从句中的列
②包含在order by,group by,distinct中的字段(联合索引)
③多表join的关联列
4. 索引列的顺序(从左到右)
①区分度最高的列放在联合索引的最左侧
②尽量把字段长度小的列放在联合索引的最左侧
③使用最频繁的列放在联合索引的最左侧
5. 避免建立冗余索引和重复索引
6. 对于频繁的查询优先考虑使用覆盖索引
R:可以把随机IO变为顺序IO加快查询效率
7. 尽量避免使用外键
R:不建议使用外键约束,但一定在表与表之间建立索引,因为外键会影响父表和子表的写操作从而降低性能,可以用其他方式来保证数据的一致性
四、数据库字段设计规范(字段类型的选择)
1. 优先选择符合存储需要的最小的数据类型
R:过大的长度会消耗更多的内存
有以下几条经验:
①将字符串转化为数字类型存储,例如将IP地址转化为数字存储,然后使用数据库自带的转换函数进行转化
②对于非负型数据来说,优先使用无符号整型来存储(无符号对于有符号多出了一倍的存储空间)
注意:Varchar(N)中的N代表的是字符数,而不是字节数(varchar(255)可以存储255个中文),即使用UTF8存储汉字varchar(255)=765个字节(一个汉字3个字节)
2. 避免使用TEXT、BLOB数据类型
R:TEXT可以存储64K的数据,非常大,很少用到,若实际情况中要使用的话,建议把BLOB或是TEXT列分离到单独的扩展表中,这样会增加主表的查询效率
3. 避免使用ENUM数据类型,且禁止使用数值作为ENUM的枚举值
4. 尽可能把所有列定义为Notnull
R:索引NULL列需要额外的空间来保存,要占用更多的空间。并且进行比较和计算时要对NULL值做特别的处理
5. 不要用字符串来存储日期型的数据,使用TIMESTAMP或DATETIME类型存储时间
6. 同财务相关的金额类数据,必须使用decimal类型
R:保证在浮点计算时不丢失精度,且decimal的占用空间由定义的宽度决定
五、数据库SQL开发规范
1. 建议使用预编译语句进行数据库操作
R:只传参数,比传递SQL语句更高效
2. 避免数据类型的隐式转换
R:隐式转换会导致索引失效
3. 充分利用表上已经存在的索引
Eg:避免使用双%号的查询条件,如 a like ‘%123%’
使用left join或not exists来优化not in操作
4. 程序连接不同的数据库使用不同的账号,禁止跨库查询
5. 禁止使用select *必须使用select <字段列表>查询
R:使用select *会消耗更多的CPU和IO以及网络带宽资源,无法使用覆盖索引。而且可减少表结构变更带来的影响
6. 禁止使用不含字段列表的insert语句
Insert into t values(‘a’,’b’,’c’)应替换为Insert into t(c1,c2,c3) values(‘a’,’b’,’c’);
R:减少表结构变更带来的影响
7. 避免使用子查询,可以把子查询优化为join操作
R:子查询的结果集无法使用索引,会消耗过多的CPU及IO资源
8. 避免使用join关联太多的表(建议不超过5个)
9. 减少同数据库的交互次数
R:数据库更适合处理批量操作,合并多个相同的操作到一起,可以提高处理效率
10. 使用in代替or
R:in可以用到索引,但in的值不要超过500个
11. 禁止使用order by rand()进行随机排序
R:order by rand()的操作是会把表中所有符合条件的数据装载到内存中,并分配一个随机值,进行排序,这样会消耗大量的CPU和IO及内存资源
解决办法:推荐在程序中获取一个随机值,然后从数据库中获取数据的方式
12. Where从句中禁止对列进行函数转换和计算
R:进行函数转换和计算则无法使用索引,例where date(createtime)=’20160901’可转换为where createtime>= ‘20160901’ and createtime< ‘20160902’
13. 在明显不会有重复值时使用UNION ALL而不是UNION
R:UNION会把所有数据放到临时表中后再进行去重操作,UNION ALL不会再对结果集进行去重操作
14. 拆分复杂的大SQL为多个小SQL
R:在MYSQL一个SQL只能使用一个CPU进行计算,SQL拆分后可以通过并行执行来提高处理效率
六、数据库操作行为规范(即手动修改)
1. 超100万行的批量写操作,要分批多次进行操作
R:大批量操作可能会造成严重的主从延迟
2. 对于大表使用pt-online-schema-change修改表结构
3. 禁止为程序使用的账号赋予super权限
R:当达到最大连接数限制时,还允许1个有super权限的用户连接,所以Super权限只能留给DBA处理问题的账号使用
4. 对于程序连接数据库账号,遵循权限最小原则