【系统设计】如何权衡范式与反范式设计

news2024/11/25 4:36:59

一、什么是范式设计与反范式设计

1.1、范式设计(Normalization)

定义:

范式设计是数据库设计中最基础的设计原则之一,它主要通过规范化数据模型,减少数据冗余和数据不一致的问题。

常用的范式

  1. 第一范式(1NF):要求数据库中的每个字段都是原子性的,即每个字段都是一个不可再分的数据项。例如,学生的姓名和成绩应分别单独作为一个字段,而不是放在同一个字段中。

  2. 第二范式(2NF):要求数据库中的每个非主键字段都完全依赖于主键。这意味着非主键字段不能依赖于其他非主键字段。例如,在一个课程信息表中,如果学分依赖于学期而不是课程编号,那么就不符合第二范式。

  3. 第三范式(3NF):要求数据库中的每个非主键字段都不依赖于其他非主键字段。换句话说,非主键字段之间不应该存在传递依赖关系。例如,在订单信息表中,如果商品价格依赖于商品编号而不是订单号,那么就不符合第三范式。

目的:

  • 消除数据冗余,提高数据的一致性和完整性。

  • 降低数据维护成本,提升数据库的扩展性、容错性及可用性。

1.2、反范式设计(Denormalization)

定义:

反范式设计是根据具体业务需求灵活地对数据库进行设计,追求更高的性能和效率。它违反了范式中的一些规则,允许部分数据的冗余和冗长,以提高查询和操作的速度。

特点:

  • 允许数据冗余,以提高查询性能。

  • 适用于需要频繁读取数据且对写入性能要求不高的场景。

范式设计的对比:

  • 范式设计注重数据的规范化和减少冗余,而反范式设计则更注重查询性能。

  • 在某些情况下,反范式设计可能会导致数据更新和维护的复杂性增加,因为需要更新多个地方的数据以确保数据的一致性。

二、系统设计与Coding方面的思考

2.1、范式设计Join查询带来的影响

场景:查询该订单下的商品信息

查询SQL:

SELECT t_sku.sku_name FROM t_order 
LEFT JOIN t_sku ON t_order.sku_id = t_sku.id WHERE order.id = 1

有什么问题:(这也是互联网公司为什么建议采用单表查询的原因)

  • 如果关联的表比较多,性能会急剧下降,产生慢sql,慢sql对系统来说是致命的;

  • 考虑分库分表

    • 如果后面存储数据过大,需要采用分库分表方案,那我们需要对SQL进行重新改造,所带来的成本跟风险都蛮大的。

如果不采用SQL进行关联查询,采用在代码层面进行Join,会有什么影响?

查询代码如下:

SELECT sku_id FROM t_order WHERE id = 1

SELECT id FROM t_sku WHERE id = id

会带来什么问题?

  • 如果数据量比较多,会对应用节点内存带来一定压力,甚至会带来FullGC

看到这里,我们其实可以用字段冗余来解决(反范式设计的体现)

我们可以在订单表里面冗余sku名称,这样就能实现需求,也能解决Join查询带来的挑战。

SELECT sku_name FROM t_order WHERE id = 1

2.2、冗余字段(反范式设计)带来的挑战

2.2.1、数据副本的一致性

  • 数据冗余:反范式化技术的主要特点之一是数据的冗余存储。这意味着相同的数据可能在多个表中都有副本。

  • 不一致的风险:当修改了某个数据副本而忘记更新其他副本时,数据就会出现不一致的情况。这种情况在更改频繁的数据中尤为突出。

更新操作的复杂性

  • 更新操作的复杂性:由于反范式化技术增加了数据冗余,每个副本都需要进行更新以维持一致性。这增加了更新操作的复杂度,并容易出错。

数据一致性的维护策略

  • 事务处理:使用事务来保证一致性,即要么所有相关的表都更新成功,要么都回滚到更新前的状态。

  • 定时器更新:在数据更新后,使用定时器来定时更新其他相关数据,确保数据的一致性。

  • 触发器:当数据被修改时,触发其他相关数据的修改,从而确保数据的一致性。

2.2.2、分布式事务

  • 数据冗余:反范式设计通过有意地冗余部分数据以提高查询性能。然而,在分库分表的场景中,这种冗余数据可能导致分布式事务的复杂性增加。

  • 一致性挑战:当修改一个数据副本时,需要确保所有相关副本都得到更新,以保持数据一致性。这涉及到跨多个数据库或数据表的事务操作。

分布式事务的复杂性

  • 跨库事务:当更新内容同时分布在不同库中时,会带来跨库事务问题。这些事务需要协调多个数据库节点,增加了事务的复杂性和执行时间。

  • 两阶段提交和XA协议:为了解决跨库事务问题,一般可使用“XA协议”和“两阶段提交”处理。这些方法虽然能最大限度保证数据库操作的原子性,但在提交事务时需要协调多个节点,推后了提交事务的时间点,延长了事务的执行时间。

分布式事务带来的其他问题

  • 性能影响:随着数据库节点的增多,分布式事务可能导致性能下降,因为每次事务都需要跨多个节点进行通信和协调。

  • 死锁和冲突:在分布式系统中,由于网络延迟和故障等因素,事务在访问共享资源时可能发生冲突或死锁,进一步增加了事务管理的复杂性。

解决方案和策略

  • 全局表:为了避免跨库join查询,可以将一些全局性的、较少修改的表(如“数据字典表”)在每个数据库中都保存一份。这样可以减少跨库事务的需求。

  • 字段冗余:一种典型的反范式设计,利用空间换时间,为了性能而避免join查询。但这种方法也增加了数据冗余和分布式事务的复杂性。

  • 最终一致性:对于性能要求高但对一致性要求不高的系统,可以采用最终一致性策略。即不苛求系统的实时一致性,而是在允许的时间段内达到最终一致性。这可以通过事务补偿、数据对账等方式实现。

2.2.3、CAP的权衡

  • 数据冗余:反范式设计通过增加数据冗余来提高查询性能。但在分库分表的场景中,这种冗余可能导致CAP权衡的复杂性增加。

一致性(Consistency)问题

  • 强一致性挑战:在分布式系统中,强一致性意味着所有节点在任何时候都看到相同的数据。然而,反范式设计引入的数据冗余可能导致在更新数据时,不同节点上的数据副本之间出现不一致。

  • 分布式事务的影响:为了保持数据的一致性,可能需要使用分布式事务来确保所有相关的数据副本都得到更新。然而,分布式事务的复杂性(如跨库事务、两阶段提交等)可能导致性能下降和可用性降低。

可用性(Availability)问题

  • 节点故障的影响:在分库分表的场景中,一个节点的故障可能导致部分数据无法访问。由于反范式设计引入了数据冗余,一个节点的故障可能影响到多个数据副本的可用性。

  • 维护数据一致性的代价:为了确保数据的一致性,可能需要采取额外的措施(如分布式锁、数据同步等),这些措施可能会降低系统的可用性。

分区容错性(Partition tolerance)问题

  • 网络分区的影响:在分布式系统中,网络分区是一个常见的问题。当网络分区发生时,系统需要能够继续运行并服务请求,即使部分节点之间无法通信。

  • 数据一致性与分区容错的权衡:在发生网络分区时,系统需要在一致性和可用性之间做出权衡。如果系统选择强一致性,可能会阻止写入操作直到所有节点都更新完成,这可能导致可用性降低。相反,如果系统选择可用性,可能会允许写入操作在部分节点上成功,但可能导致数据不一致。

解决方案和策略

  • 最终一致性:对于性能要求高但对一致性要求不高的系统,可以采用最终一致性策略。即不苛求系统的实时一致性,而是在允许的时间段内达到最终一致性。

  • 数据同步和补偿机制:为了保持数据的一致性,可以建立数据同步和补偿机制。例如,使用消息队列或日志来记录数据变更,并在后台异步地同步数据副本。

  • 分布式锁和协调服务:使用分布式锁和协调服务(如ZooKeeper、Etcd等)来协调不同节点之间的数据访问和更新操作,以确保数据的一致性。

2.3、使用场景权衡思考

数据库的范式设计与反范式设计各有其优点和适用场景。在选择使用哪种设计时,需要根据具体的业务需求、数据冗余情况、查询效率以及更新操作的频率等因素进行综合考虑。一般来说,如果业务场景对查询性能有较高要求且可以接受一定程度的数据冗余,那么反范式设计可能是一个不错的选择。而如果业务场景对数据的准确性和一致性有严格要求且希望减少数据冗余和维护成本,那么范式设计可能更为合适。

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

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

相关文章

Nginx 负载均衡实现上游服务健康检查

Nginx 负载均衡实现上游服务健康检查 Author:Arsen Date:2024/06/20 目录 Nginx 负载均衡实现上游服务健康检查 前言一、Nginx 部署并新增模块二、健康检查配置2.1 准备 nodeJS 应用程序2.2 Nginx 配置负载均衡健康检查 小结 前言 如果你使用云负载均衡…

js中的window和Window

示例: window.name name; console.log(window.name) // name console.log(Window.name) // Window由此可见Window和window是有区别的。 console.log(Object.prototype.toString.call(Window)); // [object Function] console.log(Object.prototype.toString.c…

论文:R语言数据分析之机器学习论文

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 一、研究背景 全球范围内,乳腺癌是导致癌症发病率和死亡率的主要疾病之一。根据2018年…

微软 Florence-2:多功能视觉模型

微软开发的 Florence-2 系列模型,使用提示(prompt-based approach)来处理不同的视觉任务。 通过改变提示,模型可以执行不同的任务,例如: 描述(Caption)详细描述(Detail…

代码随想录算法训练营第二十八天

题目:134. 加油站 暴力方法 暴力的方法很明显就是O(n^2)的,遍历每一个加油站为起点的情况,模拟一圈。 如果跑了一圈,中途没有断油,而且最后油量大于等于0,说明这个起点是ok的。 暴力的方法思路比较简单…

NGINX_十六 nginx 错误页面配置

十六 nginx 错误页面配置 nginx错误页面包括404 403 500 502 503 504等页面,只需要在server中增加以下配置即可: #error_page 404 403 500 502 503 504 /404.html;location /404.html {root /usr/local/nginx/html;}注意: /usr/local…

PostgreSQL性能优化之分区表 #PG培训

在处理大规模数据时,PostgreSQL的性能优化是一个非常重要的话题,其中分区表(Partitioned Tables)是提高查询和数据管理效率的重要手段。本文将详细介绍PostgreSQL分区表的概念、优势、创建与管理方法以及一些常见的优化策略。 #P…

qml:一个基础的界面设计

文章目录 文章说明效果图重要代码说明组件矩形卡片窗口最大化后组件全部居中菜单栏Repeater实现重复8行图片加载直接加载图片文本转图片FluentUI中可供选择的图标 文章说明 qt6.5.3 qml写的一个界面配置设计软件,目前不含任何c代码,纯qml。windoms风格的…

【Java】已解决java.net.HttpRetryException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例 已解决java.net.HttpRetryException异常 在Java的网络编程中,尤其是使用Apache HttpClient或其他类似的HTTP客户端库时,可能会遇到java.net.HttpRetryException异常。这个…

华为200人园区网有线和无线

实验描述: 1 内网有有线业务、内部无线、外部无线三种业误。 2 内网服务器配置静态IP,网关192.168.108.1。 3 sW1和R1之间使用v1an200 192.168.200.9/30 互联。 4 R2向运营商申请企业宽带并获得了1个固定公网IP: 200.1.1.1 子网掩码 255.255.…

VMware虚拟机下载安装Windows Server 2016

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等…

Docker常用操作和命令

文章目录 1、卸载旧版本 2、yum安装Docker CE(社区版) 3、添加镜像加速器 4、docker --version 查看docker版本 5、docker info 或 docker system info 显示 Docker 系统的详细信息,包括容器、镜像、网络等 6、docker search 搜索镜像 …

MEMS环境传感器生产测试的挑战与未来趋势

微机电系统 (MEMS) 环境传感器无处不在,默默地支撑着我们日常生活中众多设备的功能。从智能手机和可穿戴设备到智能家居和工业自动化,这些微型产品可以测量温度、压力、湿度和大量其他环境参数。 由于环境监测需求不断增长以及空气质量严格法规的实施&am…

一站式家装服务管理系统的设计

管理员账户功能包括:系统首页,个人中心,管理员管理,装修风格管理,主材管理,用户管理,基础数据管理 前台账户功能包括:系统首页,个人中心,装修风格&#xff0…

极狐GitLab落户香港科学园并成功发布AI产品驭码CodeRider国际版

GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…

189.二叉树:将有序数组转换为二叉搜索树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

canvas绘制红绿灯路口(二)

系列文章 canvas绘制红绿灯路口(一) 无图不欢,先上图 优化项: 一:加入人行道红绿信号 二:加入专用车道标识(无方向标识时采用专用车道标识) 三:东南西北四项路口优化绘…

汇凯金业:现货黄金投资平仓策略有哪些

现货黄金作为全球投资者广泛关注与参与的财富增值途径,其双向交易制度为市场参与者在不同行情下提供了盈利的可能。然而,如何在波动的市场中把握最佳的平仓时机,从而最大化收益,是所有投资者心中的疑问。正确的平仓策略可以说是现…

【GD32F303红枫派使用手册】第二十节 SPI-SPI NAND FLASH读写实验

20.1 实验内容 通过本实验主要学习以下内容: SPI通信协议,参考19.2.1东方红开发板使用手册 GD32F303 SPI操作方式,参考19.2.2东方红开发板使用手册 NAND FLASH基本原理 SPI NAND介绍 使用GD32F303 SPI接口实现对GD5F1GQ5UEYIGY的读写…

深度学习 --- stanford cs231学习笔记四(训练神经网络的几个重要组成部分之一,激活函数)

训练神经网络的几个重要组成部分 一 1,激活函数(activation functions) 激活函数是神经网络之于线性分类器的最大进步,最大贡献,即,引入了非线性。这些非线性函数可以被分成两大类,饱和非线性函…