热门标签 | 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及串口基础知识硬件:断路器、接触器、继电器基础知识



推荐阅读
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 本文深入探讨了MySQL中的高级特性,包括索引机制、锁的使用及管理、以及如何利用慢查询日志优化性能。适合有一定MySQL基础的读者进一步提升技能。 ... [详细]
  • 如何高效学习鸿蒙操作系统:开发者指南
    本文探讨了开发者如何更有效地学习鸿蒙操作系统,提供了来自行业专家的建议,包括系统化学习方法、职业规划建议以及具体的开发技巧。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • 七大策略降低云上MySQL成本
    在全球经济放缓和通胀压力下,降低云环境中MySQL数据库的运行成本成为企业关注的重点。本文提供了一系列实用技巧,旨在帮助企业有效控制成本,同时保持高效运作。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 本文由公众号【数智物语】(ID: decision_engine)发布,关注获取更多干货。文章探讨了从数据收集到清洗、建模及可视化的全过程,介绍了41款实用工具,旨在帮助数据科学家和分析师提升工作效率。 ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • 黑客松获奖名单出炉、NFT艺术周圆满落幕 |Oasis周报 ... [详细]
  • 吴石访谈:腾讯安全科恩实验室如何引领物联网安全研究
    腾讯安全科恩实验室曾两次成功破解特斯拉自动驾驶系统,并远程控制汽车,展示了其在汽车安全领域的强大实力。近日,该实验室负责人吴石接受了InfoQ的专访,详细介绍了团队未来的重点方向——物联网安全。 ... [详细]
  • 理解浏览器历史记录(2)hashchange、pushState
    阅读目录1.hashchange2.pushState本文也是一篇基础文章。继上文之后,本打算去研究pushState,偶然在一些信息中发现了锚点变 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文详细介绍了Java中HashSet的工作原理及其源码分析。HashSet实现了Set接口,内部通过HashMap来存储数据,不保证元素的迭代顺序,且允许null值的存在。文章不仅涵盖了HashSet的基本概念,还深入探讨了其内部实现细节。 ... [详细]
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社区 版权所有