热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据库:MySQL常见的设计规范误区

我们今天给大家分享MySQL设计规范中几个常见的误区,希望以后的数据库设计可以规避掉。1、主键的设计误区:主键建议使用自增ID值,尽量不要

84724e3e322db940fc4f7b082f7b5929.png

我们今天给大家分享MySQL 设计规范中几个常见的误区,希望以后的数据库设计可以规避掉。

1、主键的设计

误区:主键建议使用自增 ID 值,尽量不要使用 UUID,MD5,HASH,字符串作为数据库主键

自增主键的优点:占用空间小,有序,使用起来简单。

自增主键的不足:

  • 自增值由于在服务器端产生,需要有一把自增的  锁保护,如果业务有大量的插入请求,就可能引起的性能瓶颈。

  • 自增值做数据库主键,只能在当前数据库实例中保证唯一,不能保证全局唯一,无法在分布式架构中使用。

  • 存在数据安全,如果我们的商品 ID 是采用自增主键的话,用户可以通过修改 ID 值来获取商品,甚至可以知道我们数据库中一共存了多少个商品。

  • MGR(MySQL Group Replication) 可能引起的性能问题;

 MySQL使用 UUID() 函数来获取 UUID 的值。

MySQL> select UUID();
+--------------------------------------+
| UUID() |
+--------------------------------------+
| 15ebaa88-ce00-11eb-b431-123ac110002 |
+--------------------------------------+
1 row in set (0.00 sec)

需要特别注意的是,在存储时间类型时,UUID 是根据时间位逆序存储, 也就是低时间低位存放在最前面,高时间位在最后,即 UUID 的前 4 个字节会随着时间的变化而不断“随机”变化,并非单调递增。而非随机值在插入时会产生离散 IO,从而产生性能瓶颈。这也是 UUID 对比自增值最大的不足之处。

为了解决这个问题,MySQL 8.0 推出了函数 UUID_TO_BIN,它可以把 UUID 字符串:

  • 通过参数将时间高位放在最前,解决了 UUID 插入时乱序问题;

  • 去掉了无用的字符串"-",精简存储空间;

  • 将字符串其转换为二进制值存储,空间最终从之前的 36 个字节缩短为了 16 字节。

下面我们将之前的 UUID 字符串 23ebaa88-ce89-11eb-b123-123ac110002 通过函数 UUID_TO_BIN 进行转换,得到二进制值如下所示:

MySQL> SELECT UUID_TO_BIN('23ebaa88-ce89-11eb-b123-123ac110002',TRUE) as UUID_BIN;
+------------------------------------+
| UUID_BIN |
+------------------------------------+
| 0x11EBCE8923EBAA88B4310242AC110002 |
+------------------------------------+
1 row in set (0.01 sec)

MySQL 8.0 也提供了函数 BIN_TO_UUID,可以支持将二进制值转化为 UUID 字符串。

MySQL 8.0 之前的版可以通过自定义函数的方式解决。业务层的话可以根据相应的编程语言编写相应的函数。

而且由于 UUID 能保证全局唯一,因此使用 UUID 的好处远远大于自增 ID。可能你已经习惯了用自增做主键,但是在并发场景下,更推荐 UUID 这样的全局唯一值做主键。

但是在分布式场景下,主键还需要加入一些额外的信息,这样才能保证后续二级索引的查询效率,建议根据业务自定义生成主键。但是在并发量和数据量没那么大的情况下,还是建议使用自增 UUID 的。

2、子查询的使用

错误的设计规范:避免使用子查询

其实这个规范对老MySQL 8.0之前的版本来说是对的,因为之前版本的 MySQL 数据库对子查询优化存在很多不足,所以很多 OLTP 业务场合下,很多企业都要求在线业务避免使用子查询。

MySQL 8.0 版本中,子查询的优化得到大幅提升,所以在新版本的MySQL中可以放心的使用子查询。

采用子查询相比 JOIN 更易于阅读习惯。

3、枚举字段的使用

误区:数据库字段设计避免使用 ENUM 类型

在以前开发项目中,遇到用户性别,业务状态,星期等字段的时候,经常会简单的将字段设计为 tinyint,然后在字段注释里面说明 。

存在问题:

  • 表达不清:数据表可能是其他同事设计的,你不可能每个都记得住,每次都可能需要去看字段注释,甚至有时候在编码的时候需要去数据库确认字段的具体含义

  • 脏数据:虽然在应用层可以通过代码限制插入的数值,但是还是可以通过sql和可视化工具修改值

固定选项值的字段,推荐使用 ENUM 枚举字符串类型,再加上SQL_MODE 的严格模式

在MySQL 8.0.16 以后的版本,可以直接使用check约束机制,可以不使用enum枚举字段类型

而且我们一般在定义枚举值的时候使用"Y","N"等单个字符,并不会占用很多空间。针对选项值不固定的情况,随着业务发展可能会增加,才不推荐使用枚举字段。

3、索引个数限制

误区:限制每张表上的索引数量,索引不能超过 5 个

MySQL 单表的索引没有个数限制,要根据业务查询有具体需要,创建即可,不要太在意索引个数的限制。

4、金融字段的设计规范

误区:同财务相关的金额类数据必须使用 decimal 类型 

由于 float 和 double 都是非精准的浮点数类型,而 decimal 是精准的浮点数类型。所以一般在设计用户余额,商品价格等金融类字段一般都是使用 decimal 类型,可以精确到分。

但是在海量数据互联网业务的设计规范中,不推荐用 DECIMAL 数据类型,而是推荐将 DECIMAL 转化为整型数据类型。 金融类型更适合使用用分单位存储,而不是用元单位存储。比如5元在数据库中用整型类型 500 存储。

 bigint 类型的优点:

  • decimal 是采用二进制实现的一种编码方式,计算效率不如 bigint

  • 使用 bigint 的话,字段是定长字段,存储高效,而 decimal 根据定义的宽度决定,在数据设计中,定长存储性能更好

  • 使用 bigint 存储分为单位的金额,也可以存储千兆级别的金额数据,完全够用。

总结

  • UUID 也可以当主键,自增 UUID 比自增主键性能更好,多占用的空间也可忽略不计

  • 金融字段除了 decimal,也可以试试 bigint,存储分为单位的数据

  • 对于固定选项值的字段,MySQL8 以前推荐使用枚举字段,MySQL8 以后使用check函数约束,不要使用 0,1,2 表示

  • 一张表的索引个数并没有限制不能超过5个,可以根据业务情况

  • MySQL8 对子查询有了优化,可以放心使用。

IT技术分享社区

个人博客网站:https://programmerblog.xyz

b5d699857851ccce3c633cc8836cf458.png

文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识



推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 统一知识图谱学习和建议:更好地理解用户偏好
    本文介绍了一种将知识图谱纳入推荐系统的方法,以提高推荐的准确性和可解释性。与现有方法不同的是,本方法考虑了知识图谱的不完整性,并在知识图谱中传输关系信息,以更好地理解用户的偏好。通过大量实验,验证了本方法在推荐任务和知识图谱完成任务上的优势。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 数据库锁的分类和应用
    本文介绍了数据库锁的分类和应用,包括并发控制中的读-读、写-写、读-写/写-读操作的问题,以及不同的锁类型和粒度分类。同时还介绍了死锁的产生和避免方法,并详细解释了MVCC的原理以及如何解决幻读的问题。最后,给出了一些使用数据库锁的实际场景和建议。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
author-avatar
patrick0129_645
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有