Mysql之规范那些事

有些知识时间长了就会忘,忘了就再次翻看,所谓学而时习之,温故而知新。下面参考网上大佬博文,再次梳理学习,并将整理内容记录下来。

一、基础规范

  • 1.【推荐】尽量不在数据库做运算,复杂运算需移到业务应用里完成
  • 2.【推荐】拒绝大sql语句、拒绝大事务、拒绝大批量,可转化到业务端完成
    说明:大批量操作可能会造成严重的主从延迟,binlog日志为row格式会产生大量的日志
  • 3.【推荐】避免使用存储过程、触发器、函数等,容易造成业务逻辑与DB耦合
    说明:数据库擅长存储与索引、要解放数据库CPU,将计算转移到服务层、也具备更好的扩展性
  • 4.【强制】数据表、数据字段必须加入中文注释
    说明:后续维护的同学看到后才清楚表是干什么用的
  • 5.【强制】不在数据库中存储图片、文件等大数据
    说明:大文件和图片需要储在文件系统
  • 6.【推荐】对于程序连接数据库账号,遵循权限最小原则
  • 7.【推荐】数据库设计时,需要问下自己是否对以后的扩展性进行了考虑

二、安全规范

  • 1.【强制】禁止在数据库中存储明文密码,需把密码加密后存储
  • 2.【强制】禁止在数据库中明文存储用户敏感信息,如手机号等
  • 3.【强制】禁止开发直接给业务同学导出或者查询涉及到用户敏感信息的数据,如需要需上级领导审批
  • 4.【强制】涉及到导出数据功能的操作,如包含敏感字段都需加密或脱敏
  • 5.【强制】跟数据库交互涉及的敏感数据操作都需有审计日志,必要时要做告警
  • 6.【强制】对连接数据库的IP需设置白名单功能,杜绝非法IP接入
  • 7.【强制】对重要sql(如订单信息的查询)的访问频率或次数要做历史趋势监控,及时发现异常行为

三、命名规范

  • 1.【强制】库名、表名、字段名要小写,下划线风格,不超过32个字符,必须见名知意,建议使用名词而不是动词,词义与业务、产品线等相关联,禁止拼音英文混用
  • 2.【强制】普通索引命名格式:idx_表名_索引字段名(如果以首个字段名为索引有多个,可以加上第二个字段名,太长可以考虑缩写),唯一索引命名格式:uk_表名_索引字段名(索引名必须全部小写,长度太长可以利用缩写),主键索引命名:pk_ 字段名
  • 3.【强制】库名、表名、字段名禁止使用MySQL保留字
  • 4.【强制】临时库表名必须以tmp为前缀,并以日期为后缀
  • 5.【强制】备份库表必须以bak为前缀,并以日期为后缀
  • 6.【推荐】用HASH进行散表,表名后缀使用16进制数,下标从0开始
  • 7.【推荐】按日期时间分表需符合YYYY[MM][DD][HH]格式

四、表设计规范

  • 1.【推荐】建表规范示例
    CREATE TABLE student_info (
    id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘主键’,
    stu_name varchar(10) NOT NULL DEFAULT ‘’ COMMENT ‘姓名’,
    stu_score smallint(5) unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘总分’,
    stu_num int(11) NOT NULL COMMENT ‘学号’,
    gmt_create timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
    gmt_modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,
    status tinyint(4) DEFAULT ‘1’ COMMENT ‘1代表记录有效,0代表记录无效’,
    PRIMARY KEY (id),
    UNIQUE KEY uk_student_info_stu_num (stu_num) USING BTREE,
    KEY idx_student_info_stu_name (stu_name) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=‘学生信息表’;
  • 2.【强制】禁止使用外键,如果有外键完整性约束,需要应用程序控制
  • 3.【强制】每个Innodb 表必须有一个主键
    说明:Innodb 是一种索引组织表,其数据存储的逻辑顺序和索引的顺序是相同的。每张表可以有多个索引,但表的存储顺序只能有一种,Innodb 是按照主键索引的顺序来组织表的,因此不要使用更新频繁的列如UUID、MD5、HASH和字符串列作为主键,这些列无法保证数据的顺序增长,主键建议使用自增ID 值。
  • 4.【推荐】单表列数目最好小于50
  • 5.【强制】禁止使用分区表
    说明:分区表在物理上表现为多个文件,在逻辑上表现为一个表,谨慎选择分区键,跨分区查询效率可能更低,建议采用物理分表的方式管理大数据
  • 6.【推荐】拆分大字段和访问频率低的字段,分离冷热数据
  • 7.【推荐】采用合适的分库分表策略,例如千库十表、十库百表等(建议表大小控制在2G)
  • 8.【推荐】单表不超过50个int字段;不超过20个char字段,不超过2个text字段
  • 9.【推荐】表默认设置创建时间戳和更改时间戳字段
  • 10.【推荐】日志类型的表可以考虑按创建时间水平切割,定期归档历史数据
  • 11.【推荐】每张表数据量建议控制在500w以下,超过500w可以使用历史数据归档或分库分表来实现(500万行并不是MySQL数据库的限制。过大对于修改表结构,备份,恢复都会有很大问题。MySQL没有对存储有限制,取决于存储设置和文件系统)

五、字段设计规范

  • 1.【强制】必须把字段定义为NOT NULL并且提供默认值
    说明:NULL字段很难查询优化,NULL字段的索引需要额外空间,NULL字段的复合索引无效
  • 2.【强制】禁止使用ENUM,可使用TINYINT代替
  • 3.【强制】禁止使用TEXT、BLOB类型(如果表的记录数在万级以下可以考虑)
  • 4.【强制】必须使用varchar(20)存储手机号
  • 5.【强制】用DECIMAL代替FLOAT和DOUBLE存储精确浮点数
  • 6.【推荐】字段长度尽量按实际需要进行分配,不要随意分配一个很大的容量
  • 7.【推荐】核心表字段数量尽可能地少,有大字段要考虑拆分
  • 8.【推荐】适当考虑一些反范式的表设计,增加冗余字段,减少JOIN
  • 9.【参考】区分使用DATETIME和TIMESTAMP
    说明:存储年使用YEAR类型、存储日期使用DATE类型、存储时间(精确到秒)建议使用TIMESTAMP类型。
    DATETIME和TIMESTAMP都是精确到秒,优先选择TIMESTAMP,因为TIMESTAMP只有4个字节,而DATETIME8个字节,同时TIMESTAMP具有自动赋值以及⾃自动更新的特性。
    补充:如何使用TIMESTAMP的自动赋值属性?
    自动初始化,而且自动更新:column1 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATECURRENT_TIMESTAMP 只是自动初始化:column1 TIMESTAMP DEFAULT CURRENT_TIMESTAMP 自动更新,初始化的值为0:column1 TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP 初始化的值为0:column1 TIMESTAMP DEFAULT 0
  • 10.【参考】VARCHAR(N),N表示的是字符数不是字节数,比如VARCHAR(255),可以最大可存储255个汉字,需要根据实际的宽度来选择N
  • 11.【参考】VARCHAR(N),N尽可能小,因为MySQL一个表中所有的VARCHAR字段最大长度是65535个字节,进行排序和创建临时表一类的内存操作时,会使用N的长度申请内存
  • 12.【推荐】VARCHAR(N),N>5000时,使用BLOB类型
  • 13.【推荐】使用短数据类型,比如取值范围为0~80时,使用TINYINT UNSIGNED
  • 14.【强制】存储状态,性别等,用TINYINT
  • 15.【强制】所有存储相同数据的列名和列类型必须一致(在多个表中的字段如user_id,它们类型必须一致)
  • 16.【推荐】优先选择符合存储需要的最小数据类型
  • 17.【推荐】如果存储的字符串长度几乎相等,使用 char 定长字符串类型

六、索引设计规范

  • 1.【推荐】单表索引建议控制在5个以内
    说明:索引可以增加查询效率,但同样也会降低插入和更新的效率,甚至有些情况下会降低查询效率,所以不是越多越好
  • 2.【强制】禁止在更新十分频繁,区分度不高的属性上建立索引
  • 3.【强制】建立组合索引必须把区分度高的字段放在前面
  • 4.【推荐】对字符串使用索引,如果字符串定义长度超过128的,可以考虑前缀索引
  • 5.【强制】表必须有主键,并且是auto_increment及not null的,根据表的实际情况定义无符号的tinyint,smallint,int,bigint
  • 6.【强制】禁止更新频繁的列作为主键
  • 7.【强制】禁止字符串列作为主键
  • 8.【强制】禁止UUID MD5 HASH这些作为主键(数值太离散了)
  • 9.【推荐】默认使用非空的唯一键作为主键
  • 10.【推荐】主键建议选择自增或发号器
  • 11.【强制】不在索引列进行数学运算和函数运算
  • 12.【强制】索引字段要保证不为NULL,考虑default value进去。NULL也是占空间,而且NULL非常影响索引的查询效率
  • 13.【强制】新建的唯一索引不能和主键重复
  • 14.【强制】不在选择性低的列上建立索引,例如"性别", “状态”, “类型”
  • 15.【强制】禁止给表中的每一列都建立单独的索引

七、SQL使用规范

  • 1.【强制】禁止使用SELECT *,只获取必要的字段,需要显示说明列属性
    说明:按需获取可以减少网络带宽消耗,能有效利用覆盖索引,表结构变更对程序基本无影响。
  • 2.【强制】禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性
  • 3.【强制】WHERE条件中必须使用合适的类型,避免MySQL进行隐式类型转化
    说明:因为MySQL进行隐式类型转化之后,可能会将索引字段类型转化成=号右边值的类型,导致使用不到索引,原因和避免在索引字段中使用函数是类似的,例子 select uid from t_user where phone=15855550101(phone为 varchat 类型,此时查询中使用数字查询,会导致索引失效)
  • 4.【强制】禁止在WHERE条件的属性上使用函数或者表达式
  • 5.【强制】禁止负向查询,以及%开头的模糊查询
  • 6.【强制】应用程序必须捕获SQL异常,并有相应处理
  • 7.【推荐】sql语句尽可能简单、大的sql想办法拆成小的sql语句
    说明:简单的SQL容易使用到MySQL的querycache、减少锁表时间特别是MyISAM、可以使用多核cpu
    8.【推荐】sql中使用到OR的改写为用IN() (or的效率没有in的效率高)
    9.【推荐】limit分页注意效率。Limit越大,效率越低。可以改写limit
    说明:改写例子:
    1)改写方法一
    延迟回表写法 select xx,xx from t t1, (select id from t where … limit 10000,10) t2 where t1.id = t2.id
    2)改写方法二
    select id from t limit 10000, 10; 应该改为 => select id from t where id > 10000 limit 10;
  • 10.【强制】禁止单条SQL语句同时更新多个表
  • 11.【推荐】尽量避免使用子查询,可以把子查询优化为join操作(子查询的结果集无法使用索引,子查询会产生临时表操作,如果子查询数据量大会影响效率,消耗过多的CPU及IO资源)
  • 12.【推荐】尽量不要使用物理删除(即直接删除,如果要删除的话提前做好备份),而是使用逻辑删除,使用字段delete_flag做逻辑删除,类型为tinyint,0表示未删除,1表示已删除
  • 13.【强制】在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句
  • 14.【强制】程序连接不同的数据库要使用不同的账号
  • 15.【推荐】使用 ISNULL()来判断是否为 NULL 值

八、流程规范

  • 1.【强制】所有的建表操作需要提前告知该表涉及的查询sql
  • 2.【强制】所有的建表需要确定建立哪些索引后才可以建表上线
  • 3.【强制】所有的改表结构、加索引操作都需要将涉及到所改表的查询sql发出来告知DBA等相关人员
  • 4.【强制】在建新表加字段之前,要求至少要提前3天邮件出来,给dba们评估、优化和审核的时间
  • 5.【强制】批量导入、导出数据需要DBA进行审查,并在执行过程中观察服务
  • 6.【强制】禁止有super权限的应用程序账号存在
  • 7.【强制】推广活动或上线新功能必须提前通知DBA进行流量评估
  • 8.【强制】不在业务高峰期批量更新、查询数据库
  • 9.【强制】隔离线上线下环境(开发测试程序禁止访问线上数据库)
  • 10.【强制】在对大表做表结构变更时,如修改字段属性会造成锁表,并会造成从库延迟,从而影响线上业务,必须在凌晨后业务低峰期执行,另统一用工具pt-online-schema-change避免锁表且降低延迟执行时间
  • 11.【强制】核心业务数据库变更需在凌晨执行
  • 12.【强制】业务部门程序出现bug等影响数据库服务的问题,请及时通知DBA便于维护服务稳定
  • 13.【强制】线上数据库的变更操作必须提供对应的回滚方案
  • 14.【强制】批量清洗数据,需要开发和DBA共同进行审查,应避开业务高峰期时段执行,并在执行过程中观察服务状态
  • 15.【强制】数据订正如删除和修改记录时,要先 select ,确认无误才能执行更新语句,避免出现误删除

你可能感兴趣的:(mysql,mysql)