在网络上找到了一些资料,自认为自己之前对于MySQL相关的规范还不是很熟悉,今天就来好好梳理一下。
命名规范
基本命名规则
- 使用Snake方式命名
- 禁止超过32个字符,见名知意,建议使用名词而非动词
- 数据库和数据表的使用前缀:
- 临时库和临时表必须使用tmp作为前缀,并且日期作为后缀(后缀这个可以用来区分不同版本的临时表)
- 备份库,备份表必须使用bak作为前缀,并且日期作为后缀
操作系统对于命名的大小写敏感性
- Windows下面是不区分大小写的
- Linux下面大小写规则:
- 数据库名和表名称是严格区分大小写的
- 表的别名是严格区分大小写的
- 列名和列的别名在所有情况下均区分大小写
- 变量名也是严格区分大小写的
因此我们要规定库,表,字段的名称全部采用小写以避免问题。
如果已经设置了驼峰格式的命名,需要将MySQL的配置文件my.ini中增加 lower_case_table_names = 1
索引命名
- 非唯一索引必须按照
idx_字段名称_字段名称
命名 - 唯一索引必须按照
uniq_字段名称_字段名称
命名
约束命名
- 主键约束:
pk_表名称
- 唯一约束:
uk_表名称_字段名
表设计规范
- 表的引擎取决于应用场景,日志和报表这一类基本不需要关联查询的使用myisam,和交易,审核等等相关的建议采用innoDB引擎。
为什么说有的时候myisam更快?虽然myisam之中需要在B树之中查到数据之后再回原地址进行查询,但是相对innoDB而言,其没有MVCC特性,因此节省了MVCC部分log的时间。
- 默认使用
utf8mb4
字符集,数据库排序规则使用utf8mb4_general_ci
为什么字符集不使用utf8而使用utf8mb4呢?
utf8mb4
之中的mb4 意思为”most byte 4”,虽然根据标准,utf-8可以支持一到四个字节的长度信息存储,但是在mysql之中的utf-8只支持到3个字节的存储,即存储基本字符平面。但是emoji不属于这个,所以要进行扩张,使用utf8mb4
- 无特殊情况下,表之中的第一个id字段一定是主键并且为自动增长。禁止使用varchar类型作为主键语句设计。
我们说varchar类型作为主键的情况,一般都是UUID。而UUID对于索引很不友好。如果不是UUID,那么自增这个特性需要自己去设计,也就是自己写一个函数,比如
BH000
这种要自己去写,速度当然比int的id慢很多
- 整形之中不定义长度,比如使用 INT,而不是 INT[4]
这个里面的4只是代表宽度,而和存储范围没关系。不论M是多少,其取值范围都是(-2147483648到2147483647 有符号时),(0到4294967295无符号时)
对于声明是 INT[5] ZEROFILL的列,值 4 检索为 00004.
在整数列保存超过显示宽度的一个值的时候,MySQL为复杂链接生成临时表会遇到问题。
- 对于CHAR和VARCHAR的一点说明
- CHAR列的长度顾定位创建表时候声明的长度,可以为从0到255之间的任何值。保存CHAR的时候在其右边填充空格以达到指定的长度。
- VARCHAR之中的值是可变长字符串,其保存的时候值保存需要的字符数,使用另外一个字节来保存长度
那么什么情况适合选用什么类型呢?
- CHAR适合存储长度总是一样的值,比如 MD5 hash值。
- 如果一个值经常改变,那么char也更好,因为固定长度的行不容易产生碎片。
- 如果一个值很短,那么char的效率也好于 varchar,比如
char(1)
对于单字节字符集只会占用一个字节,但是varchar(1)
则占用两个字节,因为一个字节用来存储长度信息。
索引设计规范
合理的索引可以加快查询速度(包括UPDATE和DELETE的速度,MySQL会将包含该行的page加载到内存之中,然后进行UPDATE 和 DELETE操作)。不合理的索引会降低速度。
当MySQL查找不能使用索引的时候,其会进行全表扫描,消耗大量的IO。
索引的用途:去重,加速定位,避免排序。
- 索引不应该过多,单表之中索引不超过5个,单个索引之中的字段不超过5个。
如果有过多的索引,每次查询的时候都要对b+树进行调整,过多的索引会拖累更新的速度。
- 区分度最大的字段放在索引前面(因为最左匹配法则),同时合理的创建联合索引,比如(a,b,c)相当于(a),(a,b),(a,b,c)
- 索引的一些禁忌:
- 不在基数少的列建立索引,比如”性别“
- 不在索引列进行数学运算和函数运算
语句设计规范
- 使用预编译语句
- 只传参数,比传递SQL语句高效
- 降低SQL注入的概率
- 避免隐式转换,因为其会让索引失效
- 使用explain诊断,避免生成临时表
- 用union all 而不是 union
前者只是简单的进行合并,而后者是将数据合并之后筛选去掉重复的记录。那么union会对产生的结果集进行排序运算,删除重复的结果再返回。如果表的数据量比较大,可能会用磁盘进行排序。
- INSERT 之中必须显性的指定字段名称,
不使用 INSERT INTO table()