MySQL表结构的一些设计经验分享

我们在对一张表进行设计时,还要遵守一些基本的原则,比如经常听见的“范式准则”。但范式准则过于理论,在真实业务中,不必严格遵守三范式的要求。而且有时为了性能考虑,还可以进行反范式的设计,比如在数据仓库领域。这篇文章我们来分享些表设计的一些经验。

一、忘记范式准则

相信在大学学习《数据库系统概论》时,肯定学习过关系数据库的设计规范,比如第一范式、第二范式、第三范式,BC 范式等,它们是《数据库系统概论》考试中重要的考点。

范式设计是非常重要的理论,是通过数学集合概念来推导范式的过程,在理论上,要求表结构设计必须至少满足三范式的要求。

  • 一范式要求所有属性都是不可分的基本数据项;

  • 二范式解决部分依赖;

  • 三范式解决传递依赖。

要想真正理解范式设计,就要抛弃纯理论的范式设计准则,从业务角度出发,设计出符合范式准则要求的表结构

二、工程上的表结构设计实战

真实的业务场景是工程实现,表结构设计做好以下几点就已经足够:

  • 每张表一定要有一个主键(方法有自增主键设计、UUID 主键设计、业务自定义生成主键);

  • 消除冗余数据存在的可能。

三、自增主键设计

主键用于唯一标识一行数据,所以一张表有主键,就已经直接满足一范式的要求了。在前面文章中我们聊过可以使用 BIGINT 的自增类型作为主键,同时由于整型的自增性,数据库插入也是顺序的,性能较好。

但要注意,使用 BIGINT 的自增类型作为主键的设计仅仅适合非核心业务表,比如告警表、日志表等。真正的核心业务表,一定不要用自增键做主键,主要有 6 个原因:

  • 自增存在回溯问题;

  • 自增值在服务器端产生,存在并发性能问题;

  • 自增值做主键,只能在当前实例中保证唯一,不能保证全局唯一;

  • 公开数据值,容易引发安全问题,例如知道地址http://www.example.com/User/10/,很容猜出 User 有 11、12 依次类推的值,容易引发数据泄露;

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

  • 分布式架构设计问题。

如果你想让核心业务表用自增作为主键,MySQL 数据库版本应该尽可能升级到 8.0 版本。

四、UUID主键设计

UUID(Universally Unique Identifier)代表全局唯一标识 ID。显然,由于全局唯一性,可以把它用来作为数据库的主键。

MySQL 数据库遵循 DRFC 4122 命名空间版本定义的 Version 1规范,可以通过函数 UUID自动生成36字节字符。如:

mysql> SELECT UUID();

+--------------------------------------+

| UUID()                               |

+--------------------------------------+

| e0ea12d4-6473-11eb-943c-00155dbaa39d |

+--------------------------------------+

根据 Version 1的规范,MySQL中的 UUID 由以下几个部分组成:

UUID = 时间低(4字节)- 时间中高+版本(4字节)- 时钟序列 - MAC地址

前 8 个字节中,60 位用于存储时间,4 位用于 UUID 的版本号,其中时间是从 1582-10-15 00:00:00.00 到现在的100ns 的计数。

五、业务自定义生成主键

UUID 虽好,但是在分布式数据库场景下,主键还需要加入一些额外的信息,这样才能保证后续二级索引的查询效率(具体这部分内容将在后面的分布式章节中进行介绍)。只需要牢记:分布式数据库架构,仅用 UUID 做主键依然是不够的。 所以,对于分布式架构的核心业务表,推荐类似如下的设计,比如:

PK = 时间字段 + 随机码(可选) + 业务信息1 + 业务信息2 ......

电商业务中,订单表是其最为核心的表之一,大家可以先打开淘宝 App,查询下自己的订单号,可以查到类似如下的订单信息:

订单号显然是订单表的主键,但如果以为订单号是自增整型,那就大错特错了。如果仔细观察的话,可以发现图中所有订单号的后 6 位都是相同的,都为308113:

1550672064762308113

1481195847180308113

1431156171142308113

1431146631521308113

淘宝订单号的最后 6 位是用户 ID 相关信息,前 14 位是时间相关字段,这样能保证插入的自增性,又能同时保留业务的相关信息作为后期的分布式查询。

六、消除冗余

消除冗余也是范式的要求,解决部分依赖和传递依赖,本质就是尽可能减少冗余数据。

所以,在进行表结构设计时,数据只需存放在一个地方,其他表要使用,通过主键关联存储即可。比如订单表中需要存放订单对应的用户信息,则保存用户 ID 即可:

CREATE TABLE Orders (

  order_id VARCHRA(20),

  user_id  BINARY(16),

  order_date datetime,

  last_modify_date datetime

  ...

  PRIMARY KEY(order_id),

  KEY(user_id,order_date)

  KEY(order_date),

  KEY(last_modify_date)

)

当然了,无论是自增主键设计、UUID主键设计、业务自定义生成主键、还是消除冗余,本质上都是遵循了范式准则。但是在一些其他业务场景下,也存在反范式设计的情况。

七、反范式设计

通常我们会在 OLAP 数据分析场景中使用反范式设计,但随着 JSON 数据类型的普及,MySQL 在线业务也可以进行反范式的设计。

文章将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/621996.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++进阶:哈希(1)

目录 1. 简介unordered_set与unordered_map2. 哈希表(散列)2.1 哈希表的引入2.2 闭散列的除留余数法2.2.1 前置知识补充与描述2.2.2 闭散列哈希表实现 2.3 开散列的哈希桶2.3.1 结构描述2.3.2 开散列哈希桶实现2.3.3 哈希桶的迭代器与key值处理仿函数 3.…

Vue中常用指令

Vue中的常用指令 Vue中的常用指令内容渲染指令条件渲染指令事件绑定指令内联语句事件处理函数给事件处理函数传参 属性绑定指令列表渲染指令v-for中的key 双向绑定指令 Vue中的常用指令 概念:指令 是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。Vue 会根据不同的【…

机器人开发项目实现过程

比赛项目实现过程 第一步:设置远程桌面连接 登录机器人系统,设置网络,参考远程桌面连接20230525.mp4 外接显示器、鼠标和键盘 登录系统 账户:robuster 密码:123456 建议,手机开热点,机器人…

C++ 派生类的引入与特性

一 继承与派生 从上面的例子可以看出: 继承:一旦指定了某种事物父代的本质特征,那么它的子代将会自动具有哪些性质。这就是一种朴素的可重用的概念。 派生:而且子代可以拥有父代没有的特性,这是可扩充的概念。 1 C 的…

游戏找不到emp.dll怎么恢复,简单介绍5种有效的恢复方法

当你在启动游戏时遇到提示“找不到emp.dll”时,可能会感到有些手足无措。不要担心,这个问题其实相当常见,解决起来也并不复杂。emp.dll是一个与游戏运行环境密切相关的动态链接库文件,它的缺失可能会导致游戏无法正常启动。小编将…

【数据结构】详解队列

现在我们来掌握一下队列!如果有对往期知识有不足地方,可翻阅之前文章哦! 个人主页:小八哥向前冲~-CSDN博客 所属专栏:数据结构【c语言版】_小八哥向前冲~的博客-CSDN博客 栈和队列的实现其实都是对你顺序表和链表的检验…

Docker运行出现iptables: No chain/target/match by that name报错如何解决?

在尝试重启 Docker 容器时遇到的错误信息表明有关 iptables 的配置出了问题。这通常是因为 Docker 需要配置网络,而 iptables 规则没有正确设置或被意外删除。具体到你的错误信息中,报错 iptables: No chain/target/match by that name 表示 Docker 尝试…

【ARM Cortex-M 系列 2.2 -- Cortex-M7 单步调试原理及实现详细介绍】

请阅读【嵌入式开发学习必备专栏】 文章目录 单步调试概述单步执行原理Debug stepping control using the DHCSR 紧接上篇文章 【ARM Cortex-M 系列 2.1 – Cortex-M7 Debug system registers】 单步调试概述 在ARMv7-M架构中,通过使用单步调试(Haltin…

【工具推荐】好用的电脑文件检索工具 everything

之前每次想要检索一些电脑中的文件,软件什么之类的 只能在“我的电脑”里面,搜索 我去,真的是巨慢无比~,搜好了有些时候又忘记了,然后就得重新搜 直到我发现了…… Everything 他的名字起的确实好,想找…

Selenium + Pytest自动化测试框架实战(下)

前言 本文接上篇文章哟。 一、简单学习元素定位 在日常的工作中,我见过很多在浏览器中直接在浏览器中右键Copy Xpath复制元素的同学。这样获得的元素表达式放在 webdriver 中去运行往往是不够稳定的,像前端的一些微小改动,都会引起元素无法…

JVM的垃圾回收算法有哪些?从可达性分析算法开始,深入解读三大核心垃圾回收算法

导航: 【Java笔记踩坑汇总】Java基础JavaWebSSMSpringBootSpringCloud瑞吉外卖/黑马旅游/谷粒商城/学成在线设计模式面试题汇总性能调优/架构设计源码-CSDN博客 目录 一、概念准备 1.1 GC Roots 1.2 可达性分析算法 1.3 非可达对象被回收过程中的两次标记 1.4…

单页源码加密屋zip文件加密API源码

简介: 单页源码加密屋zip文件加密API源码 api源码里面的参数已改好,往服务器或主机一丢就行,出现不能加密了就是加密次数达到上限了,告诉我在到后台修改加密次数 点击下载

基于SpringBoot + Vue的学生宿舍课管理系统设计与实现+毕业论文(15000字)+开题报告

系统介绍 本系统包含管理员、宿管员、学生三个角色。 管理员:管理宿管员、管理学生、修改密码、维护个人信息。 宿管员:管理公寓资产、管理缴费信息、管理公共场所清理信息、管理日常事务信息、审核学生床位安排信息。 学生:查看公共场所清理…

初识C语言——第十九天

for循环 1.简单概述 2.执行流程 3.建议事项:

docker 安装 Redis (附图文教程)

首先确保已安装docker 安装docker 拉取 redis 镜像 搜索镜像 docker search redis使用最多人使用的 拉取镜像 没有指定版本默认最新版本 docker pull redis查看镜像 docker images启动容器 创建挂载目录 mkdir -p /home/local/redis/conf /home/local/redis/data创建…

【vue2项目经验总结:部署到服务器之后出现所有数据渲染失败的问题】

原因是因为在没部署到服务器之前前端为了解决跨域问题使用了代理,但是在项目部署到服务器之后,前端通常不再需要使用代理,因为代理的作用是在开发过程中帮助前端应用程序与后端服务进行通信,解决跨域访问等问题。在开发阶段&#…

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测

分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测 目录 分类预测 | Matlab实现DBO-CNN-SVM蜣螂算法优化卷积神经网络结合支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现DBO-CNN-SVM蜣螂算法…

大厂Java面试题:MyBatis中是如何实现动态SQL的?有哪些动态SQL元素(标签)?描述下动态SQL的实现原理。

大家好,我是王有志。 今天给大家带来的是一道来自京东的 MyBatis 面试题:MyBatis 中是如何实现动态 SQL 的?有哪些动态 SQL 元素(标签)?描述下动态 SQL 的实现原理。 MyBatis 中提供了 7 个动态 SQL 语句…

国际护士节庆祝活动向媒体投稿有方法很轻松

作为一名医院职工,我肩负着医院对外信息宣传的重任。在国际护士节这个特殊的日子里,我们医院举办了一系列庆祝活动,以表彰护士们的辛勤付出和无私奉献。然而,在将这些活动信息投稿至媒体的过程中,我最初却遭遇了诸多挑战。 起初,我采用传统的邮箱投稿方式,将精心撰写的稿件发送…

基于51单片机的电子门铃设计( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机电子门铃设计( proteus仿真程序设计报告原理图讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0091 1. 主要功能: 基于51单片机的智能门铃设计 1、系统采用…