遵循这些MySQL设计规范,再也没被组长喷过

2024-04-10 01:04

本文主要是介绍遵循这些MySQL设计规范,再也没被组长喷过,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

分享是最有效的学习方式。

博客:https://blog.ktdaddy.com/

故事

会议室里,小猫挠着头,心里暗暗叫苦着“哎,这代码都撸完了呀,改起来成本也太大了。”

原来就在刚才,组长找到了小猫,说代码review过程中发现有些数据表模型设计得不合理,要求小猫改掉。小猫大概是设计了一个配置表,为了省事儿,小猫直接把相关的配置设计成了text类型的存储形式。

关于这种业务场景下使用text文本类型存储,组长指出了以下缺点:

  1. 在内存中处理Text字段时,由于需要处理大量数据,可能会导致内存使用过度,影响数据库性能。
  2. Text字段无法创建索引,这会导致数据库在执行查询时无法利用索引来加速搜索。虽然可以通过全文索引来改善搜索性能,但是却会有诸多限制,例如只能用于InnoDB引擎,并且索引只能建立在不超过1000字节的前缀上。
  3. 目前刚设计的时候就用text类型,后期随着数据量的增长以及业务需求的变化,可能就意味着要将text类型继续扩大变成,LongText或MediumText类型,这样的转换既费时又可能需要额外的存储空间。

“组长说的也有道理,但是为什么现在才指出来,当时方案模型评审的时候咋提呢,哎,醉了醉了,现在业务逻辑都按照现有方案开发完了,才提出来…”

“改?要重写逻辑,不改?万一今后真的出现上面组长说的这些问题,不得被喷死…”

彷徨过后,小猫终于下定了决心,改了吧,长痛不如短痛…反正如果不改的话,受罪的还是自己。于是加班是少不了了…

数据库设计

在需求评审完毕之后,一般就是我们的技术方案的设计,在技术方案设计过程中,数据库模型设计是一个非常重要的环节。数据库模型的设计往往会影响后续业务逻辑的拓展或者直接影响着研发实际写代码的工作量。甚至会影响几代研发的维护成本。因此物理数据库的设计应该是一个非常谨慎以及严苛的过程,我们需要步步为营。

那么我们又当如何去进行数据库的设计呢?接下来,老猫从我们日常开发中用到比较多的mysql数据库的设计规范说起。如下。

在这里插入图片描述

表设计

关于表设计,咱们从以下几个方面来看。

1、 表的命名:表命名非常重要,我们要尽量去做到见名知意。

2、 根据实际场景确定引擎,咱们一般业务都会涉及到事务、行级锁等功能,所以日常开发中包括设计中咱们还是以InnoDB引擎为准。

表设计-命名规范

1、在给相关的表进行命名的时候,表名建议还是以小写英文字母和0-9数字组成(如果不涉及分表等业务场景,其实很少表名中会带有数字)以及下划线组成。虽然mysql在windows下表名不区分大小写,但是在linux下是区分大小写的,因此表名最好为小写。

2、命名需要分类区分对待,当然英文单词的命名建议使用名词而不是动词,另外的话词义应该要与业务、产品线想关联。例如我们命名一些配置类表的时候习惯以config打头,例如config_XXX。当命名临时表的时候一般tmp打头,一般为tmp_XXX,当备份表的时候那么就是bak_XXX。

3、 表命名咱们要用英文,而不是拼音或者是拼音和英文混合。记得大学刚出来的时候,那时候老猫也用拼音命名过一些表,例如设计图书管理系统的时候居然用上了shu_jia(书架)。现在想想好搓。虽然用到英文,上面提到用名词,那咱们在用名词的时候其实最好也是使用单数形式而非复数。例如员工表设计的时候,我们设计成employee而不是employees。

4、 上述还提及表名中包含数字,其实很多时候在我们分库分表的时候会用到。这里提及几个散表命名方式。首先是hash取模散表,咱们表名后缀使用16进制数,下标从0开始,或者咱们用md5进行散表那么基友user_0,user_ff等等。当然如果用到时间散表,咱们按照年月分表的时候,咱们会命名成user_202404等诸如此类。

表设计-设计规范

1、表设计的时候一般使用Innodb引擎。当然Mysql存在两种可选引擎还有一种是MyISAM。MyISAM速度快,但是不支持事务、外键以及行级锁。反观Innodb速度稍逊一筹,但是可以支持事务、外键(虽然微服务的场景下,外键很少用了)、行级锁等高级功能。

2、必须定义主键。说到主键,咱一般都是Id自增主键。有的时候咱们可能也会用到uuid或者Md5或者hash等字符串作为主键,但是这些列并不能保证数据的顺序增长。这里还是要和大家聊聊这两种主键的优缺点。方便大家后续在做表设计的时候进行取舍。老猫总结了一下,如下图:

在这里插入图片描述

3、表设计必须包含创建时间以及修改时间,用于记录创建时间和修改时间。

4、表设计的时候不要使用外键,外键影响高并发下的性能,另外的目前我们的大型项目中会涉及到分库分表,如果遇到外键的话,咱们的分库分表将会难以实施。

5、慎用触发器和存储过程。当然现在咱们应该很少会用到了,老猫只有当年在学习的时候用到了存储过程,后面实际工作的时候好像就再也没有接触过了。触发器和存储过程虽然可以减少开发量,另外封装性也好,比较安全并且不存在SQL注入问题。但是其本身可移植性是非常差的,另外的话占用服务器的资源也比较多,一旦发生错误,咱们排查问题也比较困难。互联网领域,我们现在更愿意把业务逻辑放到代码侧,变更会容易一些。

6、不要在建表的时候进行预留字段,预留字段命名很难做到见名知意,另外的话及时今后用到,在数据量大的情况下,如果类型不满足需求,我们去变更类型的时候会导致锁表。

7、单条记录的大小不要超过8kb。那么这又是为什么呢?首先,咱们从索引角度来看,innodb的页块大小默认为16kb,由于innodb采用聚簇索引(B+树结构)存放数据,每个页块中至少有两行数据,否则就失去了B+树的意义(如果每个页中只有一条数据,整个树就成了一条双向链表)。由于每个页块中至少有两行数据,可以得出一行数据的大小限制为8kb。其次,从硬盘扇区大小的角度来看,单条记录的大小一般不应该超过硬盘的扇区大小,目前硬盘的扇区大小多为4kb(只有少数是16kb),如果单条记录过大的话,查找的时候就会跨越多个扇区,增加寻道时间,可能导致性能下降。

8、单表在设计过程中,咱们最好不要超过50个int字段、20个char字段、2个text字段,另外的话单表列数也要尽量少于50,单表数量咱们也要尽量控制在500w一下,2Gb以内。如果过大的情况下,修改表结构、备份、恢复就有影响,所以当出现太大表的时候,咱们还是尽量要去分库分表。

字段设计

字段设计主要涵盖两个方面,一个是字段的命名,另外一个是字段的数据类型。咱们接下来详细看一下。

字段设计-命名规范

1、和表设计的时候一样,咱们在字段命名的过程中也尽量不要使用拼音。

2、在设计字段的时候,咱们要避免数据库关键字,比如name、time、datetime、desc等等。如果真要用到name的时候,咱们最好加上其他元素以及下划线进行组成,例如user_name、biz_name等等。

3、字段表示枚举、状态类型表示是或者否的时候,咱们最好用is打头,例如is_member,类型用unsigned tinyint(1-是 0-否) default 0。

字段设计-设计规范

1、当我们预知当前字段比较重要,或者之后查询的时候用到比较多的时候,我们肯定要加上索引,那么这种字段,咱们在进行设计的时候就必须定义成Not null,并且设置default值。例如name为非空的,那么我们的定义可能是name not null default ‘’ comment “命名”。

2、如果字段涉及小数存储的时候,我们的字段类型最好使用bigdecimal类型,而不是float或者是double,float以及double都会存在精度丢失的问题。当然有较真的小伙伴也会说bigdecimal也是有范围的,那么如果超过范围的话,应该怎么办?那么这个时候,其实我们可以将其分开进行存储,整数和小数拆开。

3、避免使用text或者blob类型存储大图片文件等信息,这种信息建议直接存储到文件系统,数据库里面可以直接存储对应的文件系统链接即可。

4、字符串类型的,咱们一般使用varchar类型,如果说存储的字符串差不多都是等长的,那么我们可以将字段设计成char定长字符串类型。另外的,varhcar类型在进行设计的时候咱们要避免设计过长,因为varchar类型在存储层面是根据实际长度存储的,但是内存分配却是根据指定长度进行的。所以如果字段设计不合理会导致内存不合理占用。

5、进行时间设计的时候,如果确定只要年月日,那么咱们就将字段设计成date类型。如果说要用到时间戳的话,那么我们要用到datetime以及timestamp。但是我们要注意这两者的区别。关于这两者的区别,老猫再此不做展开,大家有兴趣的可以自己查一下。

6、当多个表中都关联一个字段的时候,咱们应该要保证这两个字段的类型一致,以免在写代码的时候带来不必要的转换麻烦。例如tenant_id这个字段在A表中我们设计成int类型在另外一个地方又设计成了bigint,那么我们对应的代码中可能一个就是int类型另外一个地方就是Long类型。这样在实际编码的过程中就要去转换。

索引设计

聊到索引相信大家都不陌生,索引一般以索引文件的形式存储在磁盘上。我们一般所说的索引指的就是B+树结构组织的索引。

接下来咱们简单聊一下不同层面的索引的划分,然后再来聊索引相关的设计规范。

索引的分类
根据存储类型划分

聚集索引:在数据库表中物理顺序和主键顺序一致,即数据行按照主键的顺序存储。只要找到第一个索引值记录,其余的连续记录在物理层存储层面一样是连续存放。为了使得表记录和索引的排列顺序一致,插入记录会重新排序,因此修改数据比较慢。

在这里插入图片描述

非聚集索引:表记录和索引的排列顺序不一定一致,非聚集索引的叶子层并不和实际数据页相重叠,而是采用叶子层包含一个指向表记录的指针。非聚集索引层次多,不会造成数据重排。

在这里插入图片描述

关于数据库的索引的详细介绍,老猫在此不做展开。后续会有专门的文章和大家分享。

根据逻辑划分

这块大家日常应用的过程中应该还是比较常见的。咱们可以分成以下几种类型。

  1. 主键索引:特殊的唯一索引,不允许有空值。
  2. 联合索引:多个字段上建立的索引,用来提升复合查询的效率。
  3. 普通索引:属于基本索引,没有其他限制。
  4. 唯一索引:和普通索引相似,但是值必须唯一,可以用空值,常用来做幂等。
索引命名规范

咱们在给索引命名的时候需要均用英文小写字母进行命名。

主键索引:一般命名用pk_字段名称(默认一般都是id索引,在创建表的时候一般就已经指定完成了)

普通索引:咱们命名的时候一般用idx_表名_字段名称或者idx_字段名称。

唯一索引:一般用uk_表名_字段名称或者uk_字段名称。

设计规范

1、不是所有的数据库字段都适合加索引的。我们在建立索引的时候需要评估字段的区分度。应该尽量避免将索引建立在区分度低的字段上。举个例子,例如性别:男女。还有日常业务中用到的状态值、或者status-是否标记等等。

2、应当避免在频繁更新的字段上建立索引。因为每次变更都会导致B+树发生变更,频繁的变更会导致数据库的性能大大降低。

3、我们需要控制一张表中索引的数量,索引数量并不是越多越好,单表建议控制在5个以内,当然这个也要结合表字段的总数来定并非绝对。索引创建过多会增加CPU以及IO的开销。虽然索引可以提高查询效率,但是同样会降低插入以及更新的效率。

4、创建联合索引的时候尽量避免冗余。例如(a,b,c)联合索引即相当于(a)、(a,b)、(a、b、c)。另外这里其实要提到索引的最左匹配原则。当查询的时候为(a)或者(a,b)或者(a,b,c)的时候才能走到索引。如果查询是(a,c)那么其实只能走到(a)索引,这个时候其实需要注意(a)的时候返回的数据量,如果过多的话,其实语句设计就是不合理的。如果查询是(b,c)则不能走索引。
(面试官也比较喜欢问这类问题)

5、能使用唯一索引的场景,我们应该尽量去使用唯一索引。

6、如果一个字段的类型是varchar并且此时我们需要去建立相关的索引,我们此时必须要指定相关索引的长度,因为在前文中我们也提到了varchar类型存储的字符串长度往往是不固定的,如果是固定长度的咱们一般用char。我们完全没有必要对全字段建立索引,我们只要根据字段文本的区分度来建立索引即可。如下建立索引语句:

ALTER TABLE users ADD INDEX idx_email (email(10));

总结

当我们接到产品提的相关需求之后,我们就会开始进行相关的技术分析和设计,其中在设计阶段就会涉及基本的业务模型的设计。最终就是进行数据模型的设计。此时就会遇到上述的一些数据库设计的问题。

通过上述一些注意点,相信很多小伙伴应该知道数据表设计阶段的一些注意点了。如果小伙伴们还有一些需要补充的,也欢迎大家在评论区留言。分享是一种美德,大家一起进步。

这篇关于遵循这些MySQL设计规范,再也没被组长喷过的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/889697

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

Java 连接Sql sever 2008

Java 连接Sql sever 2008 /Sql sever 2008 R2 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestJDBC

Mysql BLOB类型介绍

BLOB类型的字段用于存储二进制数据 在MySQL中,BLOB类型,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储的大小不同。 TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G