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

news2024/10/6 20:33:27

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

一、忘记范式准则

相信在大学学习《数据库系统概论》时,肯定学习过关系数据库的设计规范,比如第一范式、第二范式、第三范式,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 在线业务也可以进行反范式的设计。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ATFX:美国通胀率平台期,或助力黄金延续涨势

ATFX金属:5月9日19:00至5月10日19:00,COMEX黄金的小时级别出现一波持续24小时的上涨走势,最高触及2385.3美元,累计涨幅2.78%,成为上周最佳的短线交易时机。R阻力线形成后,COMEX黄金进入下降通道&#xff0c…

采油厂职工向媒体投稿的好方法找到了

作为一名采油厂的职工,我深知在媒体上定期投稿的重要性。这不仅是我们展示工作成果、传播企业文化的重要途径,更是上级考核我们工作表现的一项指标。然而,在投稿的过程中,我经历了不少心酸与困扰。 起初,我采用传统的邮箱投稿方式。每天,我都会花费大量时间在网络上搜索合适的媒…

ms17-010(永恒之蓝)

1.漏洞介绍: 永恒之蓝(ms17-010)爆发于2017年4月14日晚,是一种利用Windows系统的SMB协议漏洞来获取系统的最高权限,以此来控制被入侵的计算机。甚至于2017年5月12日, 不法分子通过改造“永恒之蓝”制作了wannacry勒索病…

n的阶乘(函数)(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//声明n的阶乘函数fac; int fac(int n);int main() {//初始化变量值&#xff1b;int n, result;//获取要阶乘的数&#xff1b;printf("请输入要阶乘的n&…

创新点!CNN与LSTM结合,实现更准预测、更快效率、更高性能!

推荐一个能发表高质量论文的好方向&#xff1a;LSTM结合CNN。 LSTM擅长捕捉序列数据中的长期依赖关系&#xff0c;而CNN则擅长提取图像数据的局部特征。通过结合两者的优势&#xff0c;我们可以让模型同时考虑到数据的时序信息和空间信息&#xff0c;减少参数降低过拟合风险&a…

怎么通过微信小程序实现远程控制8路控制器/断路器

怎么通过微信小程序实现远程控制8路控制器/断路器呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制8路控制器/断路器&#xff0c;支持8路输出&#xff0c;均可独立控制&#xff0c;可接入各种电器。 可选用产品&#xff1a;可根据实际场景需求&#…

【2024】Gradle安装配置以及基于Kotlin 进行详细使用

目录&#x1f4bb; 一、介绍二、安装Gradle1、下载安装2、配置环境变量2.1、mac2.2、windows 3、配置国内国内镜像源4、初始化Gradle项目4.1、项目结构4.2、Gradle常用命令 三、项目配置1、配置文件介绍1.1、设置文件settings.gradle1.1.1、单体项目1.1.2、父子项目 1.2、构建文…

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…

电子学会C/C++编程等级考试2024年03月(一级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:倒序输出 依次输入4个整数a、b、c、d,将他们倒序输出,即依次输出d、c、b、a这4个数。 时间限制:1000 内存限制:65536 输入 一行4个整数a、b、c、d,以空格分隔。 0 < a,b,c,d < 108 输出 一行4个整数d、c、b、a,整数之间以…

探索人员定位系统的架构设计

随着科技的不断发展&#xff0c;人员定位系统在各个领域中扮演着越来越重要的角色。从室内定位到室外定位&#xff0c;从个人安全到物流管理&#xff0c;人员定位系统为我们提供了精准的位置信息&#xff0c;极大地促进了工作效率和安全管理。 但是&#xff0c;一个成功的人员…

docker 安装 Redis (附图文教程)

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

[算法][BFS][leetcode]994. 腐烂的橘子

题目地址 https://leetcode.cn/problems/rotting-oranges/description/ 错误解法 class Solution {public int orangesRotting(int[][] grid) {//层序遍历int ans 0;for (int i 0;i<grid.length;i) {for(int j 0;j<grid[0].length;j){boolean flag false;if(grid[i][j…

python EEL应用程序的启动过程

EEL 启动流程 初始化 EEL (eel.init()): 设定静态文件目录&#xff0c;通常是包含 HTML、CSS、JavaScript 等文件的目录。扫描指定目录下的 JavaScript 文件&#xff0c;寻找通过 eel.expose() 暴露的函数。 启动 Web 服务器 (eel.start()): 基于 Bottle 框架启动一个轻量级的 …

flexible.js+rem页面适配

简介 flexible.js 介绍 flexible.js 是一个用于移动端页面适配的 JavaScript 库&#xff0c;由阿里巴巴团队开发并开源。在移动 web 开发中&#xff0c;由于设备屏幕尺寸、分辨率以及像素比的差异&#xff0c;开发者通常需要编写额外的代码来确保页面在不同设备上都能正确显示…

AR系列路由器配置本地同一网段互通

A R 路由器是华为公司推出的企业级路由器产品系列&#xff0c;具有高可靠性、高性能和易管理等特点。AR 系列路由器提供的功能包括路由转发、安全接入、语音、视频、无线等多种业务&#xff0c;支持各种接入方式和协议&#xff0c;并且可以方便地进行扩展和升级。 实验拓扑图&…

Java面试八股之Java中的IO流分为几种

Java中的IO流分为几种 按数据单位分类&#xff1a; 字节流&#xff08;Byte Stream&#xff09;&#xff1a;以字节&#xff08;8位二进制数&#xff09;为基本单位进行数据读写。字节流适合处理所有类型的数据&#xff0c;包括文本、图像、音频、视频等二进制文件。抽象基类…

微信小程序毕业设计-基于Java后端的微信小程序源码150套(附源码+数据库+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的微信小程序毕业设计&#xff0c;后台用Java开发&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设…

STM32_HAL_系统定时器(SysTick)_实现计时

1介绍 系统定时器&#xff08;SysTick&#xff09;是ARM Cortex-M处理器系列中的一个特殊定时器&#xff0c;它不属于STM32F1系列微控制器的外设&#xff0c;而是处理器内部的一个组件。SysTick定时器的作用是为操作系统或其他需要精确时钟计数和中断服务的应用提供基础的时间…

半个小时搞懂STM32面经知识——DMA

1.DMA 1.1 什么是DMA&#xff1f; DMA传输将数据从一个地址空间复制到另一个地址空间&#xff0c;提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 CPU无时不刻的在处理着大量的事务&#xff0c;但有些事情却没有那么重要&#xff0c;比方说数据的复制和存储数…

宝塔Linux面板5.9版本升级新版失败解决方法

下载地址&#xff1a;宝塔Linux面板5.9升级教程 宝塔5.9版本升级最新版宝塔失败&#xff0c;可以参考这份详细教程&#xff08;不断更新中&#xff09; 安装要求&#xff1a; Python版本&#xff1a; 2.6/2.7&#xff08;安装宝塔时会自动安装&#xff09; 内存&#xff1a;1…