点击上方“数据不吹牛”,选择“置顶星标”公众号
干货福利,第一时间送达
因为工作岗位的原因,负责制定了关于后端组数据库的规约规范,作为所有产品线的规范,历经几版的修改,最终形成下边的文本,规范在整个后端执行也有大半年的时间,对于整个团队在开发阶段就减少不恰当的建表语句、错误SQL、错误的索引有积极的意义,故分享出来给大家参考。
下边分为建表规约、SQL规约、索引规约三个部分,每部分的每一条都有强制、建议两个级别,大家在参考时,根据自己公司的情况来权衡。
解读:InnoDB
支持事物、行级锁、并发性能更好,CPU
及内存缓存页优化使得资源利用率更高。
ID
,且这个主键ID
使用自增主键(在满足需要的情况下尽量短),除非在分库分表环境下。解读:由于InnoDB
组织数据的方式决定了需要有一个主键,而且若是这个主键ID是单调递增的可以有效提高插入的性能,避免过多的页分裂、减少表碎片提高空间的使用率。而在分库分表环境下,则需要统一来分配各个表中的主键值,从而避免整个逻辑表中主键重复。
解读:在Mysql中的UTF-8并非“真正的UTF-8”,而utf8mb4”
才是真正的“UTF-8”
。
解读:大家都别懒
解读:约定
解读:单表列数太多使得Mysql服务器处理InnoDB返回数据之间的映射成本太高
解读:外键会导致表与表之间耦合,UPDATE
与DELETE
操作都会涉及相关联的表,十分影响SQL的性能,甚至会造成死锁。
NOT NULL
并且提供默认值解读:a、NULL的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化 b、NULL这种类型Msql内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多 c、NULL值需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识
DESC、RANGE、MARCH
等,请参考Mysql
官方保留字。解读:能够减少空间碎片,节省存储空间。更多SQL技巧可搜索公号:SQL数据库开发
解读:a、这两种类型的都能表达"yyyy-MM-dd HH:mm:ss"
格式的时间,TIMESTAMP只需要占用4个字节的长度,可以存储的范围为(1970-2038)
年,在各个时区,所展示的时间是不一样的;b、而DATETIME
类型占用8个字节,对时区不敏感,可以存储的范围为(1001-9999)
年。
Schema
,建议所有的Schema
手动编写。解读:对于一些数据库客户端不要太过信任。
解读:如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()
或者CURRENT_DATE()
会因为不同的查询时间,返回不同的查询结果。
解读:a)读取不需要的列会增加CPU、IO、NET
消耗 b)不能有效的利用覆盖索引
解读:假设我们在手机号列上添加了索引,然后执行下面的SQL
会发生什么?explain SELECT user_name FROM parent WHERE phone=13812345678;
很明显就是索引不生效,会全表扫描。
解读:Mysql无法自动解析这种表达式,无法使用到索引。
解读:外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
解读:根据情况可以选择使用UNION ALL
来代替OR
解读:根据索引的最左前缀原理,%开头的模糊查询无法使用索引,可以使用ES来做检索。
解读:区分度不高的列单独创建索引的优化效果很小,但是较为频繁的更新则会让索引的维护成本更高
解读:太多表的JOIN
会让Mysql的优化器更难权衡出一个“最佳”的执行计划(可能性为表数量的阶乘),同时要注意关联字段的类型、长度、字符编码等等是否一致。
解读:索引通过第一列就能够完全定位的数据,所以联合索引的后边部分是不需要的。
解读:区分度更高的列放在左边,能够在一开始就有效的过滤掉无用数据。提高索引的效率,相应我们在Mapper
中编写SQL
的WHERE
条件中有多个条件时,需要先看看当前表是否有现成的联合索引直接使用,注意各个条件的顺序尽量和索引的顺序一致。
解读:覆盖查询即是查询只需要通过索引即可拿到所需DATA,而不再需要再次回表查询,所以效率相对很高。我们在使用EXPLAIN
的结果,extra列会出现:"using index"
。这里也要强调一下不要使用“SELECT * ”
,否则几乎不可能使用到覆盖索引。
解读:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,若长度为20的索引,区分度会高达90%以上,则可以考虑创建长度例为20的索引,而非全字段索引。例如可以使用SELECT COUNT(DISTINCT LEFT(lesson_code, 20)) / COUNT(*) FROM lesson;
来确定lesson_code
字段字符长度为20时文本区分度。
解读:1、假设有查询条件为WHERE a=? and b=? ORDER BY c;
存在索引:a_b_c
,则此时可以利用索引排序。2、反例:在查询条件中包含了范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b;
索引a_b
无法排序。
where
中索引的列不能某个表达式的一部分,也不能是函数的参数。解读:即是某列上已经添加了索引,但是若此列成为表达式的一部分、或者是函数的参数,Mysql无法将此列单独解析出来,索引也不会生效。
where
条件中使用范围查询时,索引最多用于一个范围条件,超过一个则后边的不走索引。解读:Mysql能够使用多个范围条件里边的最左边的第一个范围查询,但是后边的范围查询则无法使用。
解读:当两个表进行Join时,字段类型若没有完全一致,则加索引也不会生效,这里的完全一致包括但不限于字段类型、字段长度、字符集、collection等等
《High.Performance.MySQL.3rd.Edition》
《阿里巴巴java开发手册》
来源:juejin.im/post/6871969929365553165
●这几个数据源网站你都知道吗!?●10大Python数据可视化库!
后台回复“入群”即可加入小z数据干货交流群