safety-eval-service/docs/数据库规范.md

9.9 KiB
Raw Blame History

*数据库规范*

日期 修订版本 修订描述 编写人
2024.05.23 v01.00.00

一、 *安全规范*

  1. 【强制】禁止在数据库中存储明文密码,需把密码加密后存储

  2. 【推荐】利用审计插件(如mysqlaudit记录重要SQL的访问情况对重要sql的访问频率或次数要做历史趋势监控及时发现异常行为

  3. 【推荐】线上连接数据库统一使用数据库服务器内网IP。外网链接使用的用户名、密码定期进行更换并且统一交由@王朋管理

*二、基础规范*

  1. 【强制】库表。字符型字段mysql8字符集要求utf8mb4。排序规则utf8mb4_0900_ai_ci。为了兼容老业务系统框架 mysql5.7:字符集要求utf8。排序规则utf8_general_ci

  2. 【推荐】尽量不在数据库做运算,复杂运算需移到业务应用里完成

  3. 【推荐】拒绝大sql语句、拒绝大事务、拒绝大批量可转化到业务端完成

    说明大批量操作可能会造成严重的主从延迟binlog日志为row格式会产生大量的日志

  4. 【推荐】避免使用存储过程、触发器、函数等容易造成业务逻辑与DB耦合。

    说明数据库擅长存储与索引、要解放数据库CPU将计算转移到服务层、也具备更好的扩展性

  5. 【强制】数据表、数据字段必须加入中文注释。说明:后续维护的人看到后才清楚表是干什么用的。

  6. 【强制】不在数据库中存储图片、文件等大数据 说明:大文件和图片需要储在文件系统。

  7. 【推荐】对于程序连接数据库账号,遵循权限最小原则

  8. 【推荐】数据库设计时,需要问下自己是否对以后的扩展性进行了考虑。

  9. 【推荐】数据库开启slow_query_log并定期分析进行优化。

  10. 【推荐】如果数据量或数据增长在前期规划时就较大,那么在设计评审时就应加入分表策略。

  11. 【推荐】要求所有研发SQL关键字全部是小写每个词只允许有一个空格。

  12. 【强制】定期自动执行数据库备份,包括全量备份和增量备份。

*三、命名规范*

  1. 【强制】mysql8:库名、表名、字段名要小写下划线风格不超过32个字符为了兼容老业务系统框架 mysql5.7:库名表名为小写+下划线,字段名为大写+下划线)必须见名知意,建议使用名词而不是动词,词义与业务、产品线等相关联,禁止拼音英文混用。
  2. 【强制】库名、表名、字段名禁止使用MySQL保留字
  3. 【强制】临时库表名必须以tmp为前缀并以日期为后缀
  4. 【强制】备份库表必须以back_日期为后缀
  5. 【推荐】按日期时间分表需符合按年分表表名_ YYYY 按月分表表名_ YYYYMM格式
  6. 【强制】表达是与否概念的字段,禁止使用 is_xxx 的方式命名一律使用xxx_flag的方式命名数据类型是 tinyint1 表示是2 表示否,尽量不使用0

*四、库设计规范*

  1. 【推荐】数据库使用InnoDB存储引擎

  2. 【强制】禁止使用外键,如果有外键完整性约束,需要应用程序控制

  3. 【强制】每个Innodb 表必须有且只有一个主键。

    说明:多主键可能导致聚簇索引无法正确被使用。

  4. 【推荐】单表列数目最好小于50

  5. 【推荐】拆分大字段和访问频率低的字段,分离冷热数据

  6. 【推荐】采用合适的分库分表策略例如千库十表、十库百表等建议表大小控制在2G

  7. 【推荐】单表不超过50个int字段不超过20个char字段不超过2个text字段

  8. 【推荐】日志类型的表可以考虑按创建时间水平切割,定期归档历史数据

  9. 【强制】禁止使用order by rand()

    说明order by rand()会为表增加一个伪列然后用rand()函数为每一行数据计算出rand()值,基于该行排序,这通常都会生成磁盘上的临时表,因此效率非常低。

  10. 【参考】可以结合使用hash、range、lookup table进行散表

  11. 【强制】业务主表中必须有creator,create_time,operator,operate_time,is_delete五个字段垂直拆分的附表可以没有

  12. 【强制】禁止在表中建立预留字段

    说明:预留字段的命名很难做到见名识义,预留字段无法确认存储的数据类型,所以无法选择合适的类型;对预留字段类型的修改,会对表进行锁定

*五**、**字段设计规范*

  1. 【强制】禁止使用小数存储国币、使用“分”作为单位,这样数据库里就是整数了

  2. 【强制】用DECIMAL代替FLOAT和DOUBLE存储精确浮点数

  3. 【强制】字段长度尽量按实际需要进行分配,不要随意分配一个很大的容量

  4. 【推荐】适当增加冗余字段减少JOIN

  5. 【强制】表示状态的字段如is_delete、state等使用INT禁止使用 VARCHAR

  6. 【参考】VARCHAR(N)N表示的是字符数不是字节数比如VARCHAR(255)可以最大可存储255个汉字需要根据实际的宽度来选择N

  7. 【参考】VARCHAR(N)N尽可能小因为MySQL一个表中所有的VARCHAR字段最大长度是65535个字节进行排序和创建临时表一类的内存操作时会使用N的长度申请内存

  8. 【推荐】VARCHAR(N)N>5000时使用BLOB类型

  9. 【推荐】使用短数据类型比如取值范围为0~80时使用TINYINT UNSIGNED

  10. 【强制】存储状态性别等用TINYINT

  11. 【强制】所有存储相同数据的列名和列类型必须一致在多个表中的字段如user_id它们类型必须一致

  12. 【推荐】优先选择符合存储需要的最小数据类型

  13. 【推荐】如果存储的字符串长度几乎相等,使用 char 定长字符串类型

六、索引设计规范

  1. 【强制】索引命名必须遵循规范:普通索引使用idx_字段名,唯一索引使用uk_字段名

  2. 【推荐】核心SQL优先考虑覆盖索引

  3. 【推荐】区分度高重复值少、频繁作为WHERE条件的字段应建立索引

    说明区分度计算公式count(distinct col)/count(col)区分度越高索引效果越好一般认为超过0.1的字段适合建索引

  4. 【参考】避免冗余和重复索引

  5. 【推荐】研发要经常使用explain如果发现索引选择性差必须要学会使用hint

  6. 【推荐】能使用唯一索引就要使用唯一索引,提高查询效率

  7. 【强制】了解索引失效场景,避免以下用法:

    • 使用 LIKE '%xxx'LIKE '%xxx%'(前缀模糊 LIKE 'xxx%' 可使用索引)
    • 在索引列上进行计算、函数操作
    • 隐式类型转换(如字符串字段用数字查询)
    • 使用 OR 连接条件(部分情况)
    • 使用 !=<>NOT INIS NULLIS NOT NULL
    • 联合索引未遵循最左前缀原则
  8. 【推荐】多条字段重复的语句,要修改语句条件字段的顺序,为其建立一条联合索引,减少索引数量

  9. 【推荐】WHERE条件中的非等值条件IN、BETWEEN、<、<=、>、>=)会导致后面的条件使用不了索引

  10. 【参考】合理创建联合索引(避免冗余),如(a,b,c) 相当于 (a) 、(a,b) 、(a,b,c)

  11. 【推荐】复合索引中的字段数建议不超过5个

  12. 【推荐】联合索引遵循最左前缀原则,将区分度高的字段放在前面

    说明:查询条件必须包含联合索引的第一列(最左列),索引才会生效

  13. 【强制】禁止给表中的每一列都建立单独的索引

*七、SQL使用规范*

  1. 【强制】WHERE条件中必须使用合适的类型避免MySQL进行隐式类型转化

    说明因为MySQL进行隐式类型转化之后可能会将索引字段类型转化成=号右边值的类型,导致使用不到索引,原因和避免在索引字段中使用函数是类似的,例子 select uid from t_user where phone=15855550101phone为 varchar 类型,此时查询中使用数字查询,会导致索引失效)

  2. 【推荐】禁止在WHERE条件的属性上使用函数或者表达式

  3. 【强制】应用程序必须捕获SQL异常并有相应处理

  4. 【推荐】sql语句尽可能简单、大的sql想办法拆成小的sql语句减少锁表时间

  5. 【推荐】事务要简单,整个事务的时间长度不要太长

  6. 【强制】避免在数据库中进行数学运算或者函数运算(MySQL不擅长数学运算和逻辑判断也容易将业务逻辑和DB耦合在一起)

  7. 【推荐】sql中使用到OR的改写为用IN() (or的效率没有in的效率高)

  8. 【推荐】尽量使用union all替代union

  9. 【参考】避免使用大表JOIN

  10. 【推荐】使用合理的SQL语句减少与数据库的交互次数

  11. 【强制】禁止单条SQL语句同时更新多个表

  12. 【推荐】获取大量数据时建议分批次获取数据每次获取数据少于2000条结果集应小于1M

  13. 【强制】禁止跨库查询(为数据迁移和分库分表留出余地,降低耦合度,降低风险)

  14. 【推荐】尽量避免使用子查询可以把子查询优化为join操作子查询的结果集无法使用索引子查询会产生临时表操作如果子查询数据量大会影响效率消耗过多的CPU及IO资源

  15. 【推荐】SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts最好

  16. 【强制】不要使用物理删除。0表示未删除1表示已删除

  17. 【强制】在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句

  18. 【推荐】使用 ISNULL()来判断是否为 NULL 值