背景

因为工作岗位的原因,负责制定了关于后端组数据库的规约规范,作为所有产品线的规范,历经几版的修改,最终形成下边的文本,规范在整个后端执行也有大半年的时间,对于整个团队在开发阶段就减少不恰当的建表语句、错误SQL、错误的索引有积极的意义,故分享出来给大家参考。

下边分为建表规约、SQL规约、索引规约三个部分,每部分的每一条都有强制、建议两个级别,大家在参考时,根据自己公司的情况来权衡。

一、建表规约

【强制】(1) 存储引擎必须使用InnoDB

解读:InnoDB支持事物、行级锁、并发性能更好,CPU及内存缓存页优化使得资源利用率更高。

【强制】(2)每张表必须设置一个主键ID,且这个主键ID使用自增主键(在满足需要的情况下尽量短),除非在分库分表环境下。

解读: 由于InnoDB组织数据的方式决定了需要有一个主键,而且若是这个主键ID是单调递增的可以有效提高插入的性能,避免过多的页分裂、减少表碎片提高空间的使用率。 而在分库分表环境下,则需要统一来分配各个表中的主键值,从而避免整个逻辑表中主键重复。

【强制】(3)必须使用utf8mb4字符集

解读:在Mysql中的UTF-8并非“真正的UTF-8”,而utf8mb4”才是真正的“UTF-8”

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

解读:大家都别懒

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

解读:约定

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

解读:单表列数太多使得Mysql服务器处理InnoDB返回数据之间的映射成本太高

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

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

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

解读: a、NULL的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化 b、NULL这种类型Msql内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多 c、NULL值需要更多的存储空,无论是表还是索引中每行中的NULL的列都需要额外的空间来标识

【强制】(9)禁用保留字,如DESC、RANGE、MARCH等,请参考Mysql官方保留字。

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

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

【建议】(11)在一些场景下,考虑使用TIMESTAMP代替DATETIME。

解读: a、这两种类型的都能表达"yyyy-MM-dd HH:mm:ss"格式的时间,TIMESTAMP只需要占用4个字节的长度,可以存储的范围为(1970-2038)年,在各个时区,所展示的时间是不一样的; b、而DATETIME类型占用8个字节,对时区不敏感,可以存储的范围为(1001-9999)年。

【建议】(12)当心自动生成的Schema,建议所有的Schema手动编写。

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


二、SQL规约

【建议】 (1) 为了充分利用缓存,不允许使用自定义函数、存储函数、用户变量。

解读: 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果。

【强制】(2)在查询中指定所需的列,而不是直接使用“ *”返回所有的列

解读: a)读取不需要的列会增加CPU、IO、NET消耗 b)不能有效的利用覆盖索引

【强制】(3)不允许使用属性隐式转换

解读: 假设我们在手机号列上添加了索引,然后执行下面的SQL会发生什么? explain SELECT user_name FROM parent WHERE phone=13812345678; 很明显就是索引不生效,会全表扫描。

【建议】(4)在WHERE条件的属性上使用函数或者表达式

解读:Mysql无法自动解析这种表达式,无法使用到索引。

【强制】(5)禁止使用外键与级联,一切外键概念必须在应用层解决。

解读: 外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

【建议】(6)应尽量避免在WHERE子句中使用or作为连接条件

解读:根据情况可以选择使用UNION ALL来代替OR

【强制】(7)不允许使用%开头的模糊查询

解读:根据索引的最左前缀原理,%开头的模糊查询无法使用索引,可以使用ES来做检索。


三、索引规约

【建议】(1)避免在更新比较频繁、区分度不高的列上单独建立索引

解读: 区分度不高的列单独创建索引的优化效果很小,但是较为频繁的更新则会让索引的维护成本更高

【强制】(2) JOIN的表不允许超过五个。需要JOIN的字段,数据类型必须绝对一致; 多表关联查询时,保证被关联的字段需要有索引。

解读: 太多表的JOIN会让Mysql的优化器更难权衡出一个“最佳”的执行计划(可能性为表数量的阶乘),同时要注意关联字段的类型、长度、字符编码等等是否一致。

【强制】(3)在一个联合索引中,若第一列索引区分度等于1,那么则不需要建立联合索引。

解读:索引通过第一列就能够完全定位的数据,所以联合索引的后边部分是不需要的。

【强制】(4)建立联合索引时,必须将区分度更高的字段放在左边

解读: 区分度更高的列放在左边,能够在一开始就有效的过滤掉无用数据。提高索引的效率,相应我们在Mapper中编写SQLWHERE条件中有多个条件时,需要先看看当前表是否有现成的联合索引直接使用,注意各个条件的顺序尽量和索引的顺序一致。

【建议】(5)利用覆盖索引来进行查询操作,避免回表

解读: 覆盖查询即是查询只需要通过索引即可拿到所需DATA,而不再需要再次回表查询,所以效率相对很高。我们在使用EXPLAIN的结果,extra列会出现:"using index"。这里也要强调一下不要使用“SELECT * ”,否则几乎不可能使用到覆盖索引。

【建议】(6)在较长VARCHAR字段,例如VARCHAR(100)上建立索引时,应指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。

解读:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,若长度为20的索引,区分度会高达90%以上,则可以考虑创建长度例为20的索引,而非全字段索引。 例如可以使用SELECT COUNT(DISTINCT LEFT(lesson_code, 20)) / COUNT(*) FROM lesson;来确定lesson_code字段字符长度为20时文本区分度。

【建议】(7)如果有ORDER BY的场景,请注意利用索引的有序性。ORDER BY最后的字段是联合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。

解读: 1、假设有查询条件为WHERE a=? and b=? ORDER BY c; 存在索引:a_b_c,则此时可以利用索引排序。 2、反例:在查询条件中包含了范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。

【建议】(8)在where中索引的列不能某个表达式的一部分,也不能是函数的参数。

解读:即是某列上已经添加了索引,但是若此列成为表达式的一部分、或者是函数的参数,Mysql无法将此列单独解析出来,索引也不会生效。

【建议】 (9)我们在where条件中使用范围查询时,索引最多用于一个范围条件,超过一个则后边的不走索引。

解读:Mysql能够使用多个范围条件里边的最左边的第一个范围查询,但是后边的范围查询则无法使用。

【建议】 (10)在多个表进行外连接时,表之间的关联字段类型必须完全一致

解读:当两个表进行Join时,字段类型若没有完全一致,则加索引也不会生效,这里的完全一致包括但不限于字段类型、字段长度、字符集、collection等等

参考

  • 《High.Performance.MySQL.3rd.Edition》
  • 《阿里巴巴java开发手册》

这些数据库通用规约,你都遵守了吗?相关推荐

  1. 常见的关系型数据库和非关系型都有哪些?

    常见的关系型数据库和非关系型都有哪些? 关系型数据库: 关系模型就是指二维表格模型,因而一个关系型数据库就是由二维表及其之间的联系组成的一个数据组织. 常见的有:Oracle.DB2.PostgreS ...

  2. 微服务springCloud 项目实战 创建数据库表规约及建表语句

    # 创建数据库表规约及建表语句 1.建表规约 **[强制]**表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是tinyint(1) ( 1表示是,0表示否). 说明:任何字段如果为非负 ...

  3. 【技术应用】【informix】 c++版 数据库通用操作

    事物的存在都有它存在的价值, 为了简化工作量,曾经使用esql写过一个通用操作,这个是c++版本的,刚写完没有实际应用测试 实现以下功能 1.  数据库的基本操作,添加,删除,修改,查询 2.  查询 ...

  4. 分库分表 PK NewSQL数据库!看了都说好!

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Sometimes people only change because o ...

  5. C#.NET操作数据库通用类(MS SQL Server篇)

    下面给出了一个C#操作MS SQL Server 数据库的通用类,通过该类可以对数据库进行任何操作,包括执行SQL语句.执行存储过程.以下是其详细实现过程,希望大家共同修改优化之.稍后将介绍如何使用它 ...

  6. C#.NET操作数据库通用类

    下面给出了一个C#操作MS SQL Server 数据库的通用类,通过该类可以对数据库进行任何操作,包括执行SQL语句.执行存储过程.以下是其详细实现过程,希望大家共同修改优化之.稍后将介绍如何使用它 ...

  7. 今天修改了数据库结构,XSD文件都要重新生成,郁闷!

    今天修改了一下数据库其中一个表的结构,结果导致整个XSD文件都要修改,搞的真是焦头烂额,所以,有时候真的不好说是ELB好用还是使用强类型集更好用,如果真的使用强类型集的时候,建议你一定要先规划好数据库 ...

  8. java数据库连接类,已经把数据库操作的方法都封装好了

    在这里分享一个已经封装好了的java数据库连接类,只要创建对象就可以实现数据库的增删改查操作,用过都说好.其实这个不是我自己写的,是一个理解和学习能力超高的朋友写的,他也很乐于分享交流,本人也深受他的 ...

  9. DbHelper数据库通用类使用方法

    代码 //执行SQL语句 public static void ExecSqlCommand() { DbHelper db = new DbHelper(); DbCommand command = ...

最新文章

  1. Ubuntu12.10编译openwrt遇到的错误
  2. C语言读写配置文件--转载
  3. 虚拟机从暂停状态恢复后HEALTH_WARN,osds down
  4. Network下方什么请求也没有_今日头条上传图片时设置封面图报像素低的原因是什么...
  5. 微型计算机用什么评价判断,环评中常用评价等级的判定
  6. aws dynamodb_如何使用AWS Lambda将DynamoDB集成到您的API中
  7. 云计算之路-阿里云上:Web服务器请求到达量突降
  8. Android中SurfaceView用法示例
  9. 视频会议中回声消除与噪音抑制的技巧
  10. 一点桌面计算机为什么打开方式,电脑默认软件打开方式 电脑上默认打开方式在哪设置...
  11. Android应用启动白屏问题解决办法
  12. matlab批量将mp3文件转wav文件
  13. RecyclerView刷新布局时Glide加载图片闪现
  14. python字典概述
  15. R语言基于方差分析ANOVA检验模型拟合度(Fit Test)实战:检验同一数据集简单模型和复杂模型的拟合度差异
  16. Python 变量作用域问题 函数名.变量名
  17. 好莱坞经典十大战争电影排行榜 男人必看十大战争片
  18. python中字符串输出乱码怎么解决_python字符乱码的解决小结
  19. C语言 存储类型关键字详解
  20. ajax post无效,jQuery AJAX Post无效

热门文章

  1. Java判断多个时间段是否重叠
  2. FreeRTOS-实现任务调度器
  3. Note7爆炸答案揭晓,三星重树市场新形象
  4. java uint8array_php字符串转数组等效于js的new Uint8Array(readAsArrayBuffer)
  5. 我不怕千万人阻挡,只怕自己投降
  6. python解析器的安装指导教程
  7. reddit_如何启用Reddit的黑暗模式
  8. Docker: network nat is ambigous
  9. 论文阅读:大型对抗性不完美信息博弈的均衡发现 AAAI/ACM SIGAI Best Paper
  10. 在linux系统里安装软件,请问在linux系统里怎样安装软件