解读阿里巴巴开发规范之MySQL

DevOpSec
• 阅读 1434

前言

从7月份毕业开始算起,也是将近有5个月的工作经验了吧。在工作上,经历了一段时间的适应,现在接触到不同大神写出来的代码,发现各有优劣,于是就在思考一个问题,什么样的代码才是最正常最规范的呢?我的同事甩给我了一本《阿里巴巴Java开发手册》,从头到尾也算是过了一遍。今天趁着双休的假期,我就来讲一下这本书里面的MySQL规范制约吧~

阿里巴巴开发规范之MySQL

建表规约

1、【强制】每张表必须设置一个主键ID,并且这个主键ID要自增(在满足需要的情况下尽量短),除非是分库分表

理解:由于InnoDB存储引擎决定了需要有一个主键,而且这个主键ID是自增的话可以有效提高插入的性能,避免过多的页分裂,减少表碎片提高空间的利用率。

但是在分库分表下,会有分片规则,这个时候需要统一分配各个表中的主键值,从而避免整个逻辑表中主键重复,一般我们会使用雪花ID来实现。

2、【强制】必须使用utf8mb4字符集

理解:在MySQL中的UTF-8并非是真正的"UTF-8",而utf8mb4才是真正的"UTF-8"。

3、【强制】数据库表、表字段必须加入中文注释

理解:程序员都不要给我懒,这样可以让后来者更好的上手和理解。

4、【强制】库名、表名、字段名必须小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用

理解:在linux环境下MySQL是区分大小写的,而在windows是不区分大小写的,所以统一使用小写+下划线可以避免不必要的混淆。

5、【强制】单表列数目必须小于30,若超过则应该考虑将表拆分

理解:单表列数太多会使得MySQL处理InnoDB返回数据之间的映射成本太高。

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

理解:外键会导致表与表之间耦合,UPDATE与DELETE操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。

7、【强制】必须把字段定义为NOT NULL并且提供默认值

理解:NULL需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识。NULL这种类型需要MySQL内部进行特殊处理,增加了数据库处理记录的复杂性,同等条件下,表中较多NULL字段会导致数据库处理性能下降。

8、【强制】禁止使用保留字,如DESC、RANGE、MAX等

理解:请参考MySQL官方保留字。

9、【强制】如果存储的字符串长度几乎相等,使用CHAR定长字符串类型

理解:能够减少空间碎片,节省存储空间。

10、【强制】小数类型为 decimal,禁止使用 float 和 double

理解:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。

11、【强制】表必备三字段:id, gmt_create, gmt_modified。

理解:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。gmt_create,gmt_modified 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被动更新。

12、【推荐】在一些场景下,考虑使用TIMESTAMP代替DATETIME

理解:TIMESTAMP可以表达1970-2038年,而且TIMESTAMP需要4字节存储空间,而DATETIME需要8字节,存储1001-9999年

13、【推荐】对于自动生成的schema不要太过信任,最好自己手动写

理解:对于一些数据库客户端不要过分信任。

索引规约

1、【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引

理解:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

2、【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引

理解:多表的join操作会影响SQL的性能

3、【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可

理解:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度来确定。

4、【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决

理解:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

5、【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能

理解:组合索引的顺序会影响到SQL的查询性能

6、【推荐】利用覆盖索引来进行查询操作,避免回表

理解:覆盖索引只需要通过索引即可拿到所需的数据,而不再需要再次回表查询,提高了SQL的查询效率。

7、【推荐】利用延迟关联或者子查询优化超多分页场景

理解:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

8、【推荐】建组合索引的时候,区分度最高的在最左边

理解:区分度最高的放左边,能够在一开始过滤掉很多无用数据,提高索引的效率。需要注意的是各个条件的顺序尽量和索引的顺序一致。

9、【推荐】防止因字段类型不同造成的隐式转换,导致索引失效

理解:详细细节可以参考这篇文章哦~MySQL索引(三)索引不生效的情况

SQL规约

1、【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关

理解:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

2、【强制】使用 ISNULL()来判断是否为 NULL 值

理解:NULL与任何值直接比较都为NULL。

  1. NULL<>NULL返回结果是NULL,而不是false。
  2. NULL=NULL返回结果是NULL,而不是false。
  3. NULL&1返回结果是NULL,而不是true。

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

理解:提高SQL的效率,避免不必要的无用查询。

4、【强制】不得使用外键与级联,一切外键概念必须在应用层解决

理解:外键会导致表与表之间耦合,UPDATE与DELETE操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。

5、【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性

理解:避免不必要的维护。

6、【推荐】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。

理解:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

参考

  • 《阿里巴巴Java开发手册》
  • 实际工作结合《阿里巴巴Java开发手册》得出的理解

本文转自 https://blog.csdn.net/weixin_37686415/article/details/110276789?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
DevOpSec
DevOpSec
Lv1
懂开发的运维,懂安全的运维。公众号:DevOpSec
文章
57
粉丝
6
获赞
26