MySQL的部分规范梳理

Posted by Haiming on September 21, 2020

在网络上找到了一些资料,自认为自己之前对于MySQL相关的规范还不是很熟悉,今天就来好好梳理一下。

参考

命名规范

基本命名规则

  1. 使用Snake方式命名
  2. 禁止超过32个字符,见名知意,建议使用名词而非动词
  3. 数据库和数据表的使用前缀:
    1. 临时库和临时表必须使用tmp作为前缀,并且日期作为后缀(后缀这个可以用来区分不同版本的临时表)
    2. 备份库,备份表必须使用bak作为前缀,并且日期作为后缀

操作系统对于命名的大小写敏感性

  1. Windows下面是不区分大小写的
  2. Linux下面大小写规则:
    1. 数据库名表名称是严格区分大小写的
    2. 表的别名是严格区分大小写的
    3. 列名列的别名在所有情况下均区分大小写
    4. 变量名也是严格区分大小写的

因此我们要规定库,表,字段的名称全部采用小写以避免问题。

如果已经设置了驼峰格式的命名,需要将MySQL的配置文件my.ini中增加 lower_case_table_names = 1

索引命名

  1. 非唯一索引必须按照idx_字段名称_字段名称命名
  2. 唯一索引必须按照uniq_字段名称_字段名称命名

约束命名

  1. 主键约束:pk_表名称
  2. 唯一约束:uk_表名称_字段名

表设计规范

  1. 表的引擎取决于应用场景,日志和报表这一类基本不需要关联查询的使用myisam,和交易,审核等等相关的建议采用innoDB引擎。

为什么说有的时候myisam更快?虽然myisam之中需要在B树之中查到数据之后再回原地址进行查询,但是相对innoDB而言,其没有MVCC特性,因此节省了MVCC部分log的时间。

  1. 默认使用utf8mb4字符集,数据库排序规则使用utf8mb4_general_ci

为什么字符集不使用utf8而使用utf8mb4呢?

utf8mb4之中的mb4 意思为”most byte 4”,虽然根据标准,utf-8可以支持一到四个字节的长度信息存储,但是在mysql之中的utf-8只支持到3个字节的存储,即存储基本字符平面。但是emoji不属于这个,所以要进行扩张,使用utf8mb4

  1. 无特殊情况下,表之中的第一个id字段一定是主键并且为自动增长。禁止使用varchar类型作为主键语句设计。

我们说varchar类型作为主键的情况,一般都是UUID。而UUID对于索引很不友好。如果不是UUID,那么自增这个特性需要自己去设计,也就是自己写一个函数,比如BH000这种要自己去写,速度当然比int的id慢很多

  1. 整形之中不定义长度,比如使用 INT,而不是 INT[4]

这个里面的4只是代表宽度,而和存储范围没关系。不论M是多少,其取值范围都是(-2147483648到2147483647 有符号时),(0到4294967295无符号时)

对于声明是 INT[5] ZEROFILL的列,值 4 检索为 00004.

在整数列保存超过显示宽度的一个值的时候,MySQL为复杂链接生成临时表会遇到问题。

  1. 对于CHAR和VARCHAR的一点说明
  1. CHAR列的长度顾定位创建表时候声明的长度,可以为从0到255之间的任何值。保存CHAR的时候在其右边填充空格以达到指定的长度。
  2. VARCHAR之中的值是可变长字符串,其保存的时候值保存需要的字符数,使用另外一个字节来保存长度

那么什么情况适合选用什么类型呢?

  1. CHAR适合存储长度总是一样的值,比如 MD5 hash值。
  2. 如果一个值经常改变,那么char也更好,因为固定长度的行不容易产生碎片。
  3. 如果一个值很短,那么char的效率也好于 varchar,比如 char(1)对于单字节字符集只会占用一个字节,但是varchar(1)则占用两个字节,因为一个字节用来存储长度信息。

索引设计规范

合理的索引可以加快查询速度(包括UPDATE和DELETE的速度,MySQL会将包含该行的page加载到内存之中,然后进行UPDATE 和 DELETE操作)。不合理的索引会降低速度。

当MySQL查找不能使用索引的时候,其会进行全表扫描,消耗大量的IO。

索引的用途:去重,加速定位,避免排序。

  1. 索引不应该过多,单表之中索引不超过5个,单个索引之中的字段不超过5个。

如果有过多的索引,每次查询的时候都要对b+树进行调整,过多的索引会拖累更新的速度。

  1. 区分度最大的字段放在索引前面(因为最左匹配法则),同时合理的创建联合索引,比如(a,b,c)相当于(a),(a,b),(a,b,c)
  2. 索引的一些禁忌:
    1. 不在基数少的列建立索引,比如”性别“
    2. 不在索引列进行数学运算和函数运算

语句设计规范

  1. 使用预编译语句
    1. 只传参数,比传递SQL语句高效
    2. 降低SQL注入的概率
  2. 避免隐式转换,因为其会让索引失效
  3. 使用explain诊断,避免生成临时表
  4. 用union all 而不是 union

前者只是简单的进行合并,而后者是将数据合并之后筛选去掉重复的记录。那么union会对产生的结果集进行排序运算,删除重复的结果再返回。如果表的数据量比较大,可能会用磁盘进行排序。

  1. INSERT 之中必须显性的指定字段名称,不使用 INSERT INTO table()