数据库逻辑设计
时间:2022-05-07
本文章向大家介绍数据库逻辑设计,主要内容包括数据库设计、数据库结构优化的目的、第三范式、反范式化、总结、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
数据库设计
数据库设计包含需求设计、逻辑设计、物理设计和维护优化。
- 需求分析:全面了解产品设计的存储需求(存储需求,数据处理需求,数据的安全性和完整性)
- 逻辑设计:设计数据的逻辑存储结构(数据实体之间的逻辑关系,解决数据冗余和数据维护异常 )
- 物理设计:根据所使用的数据库特点进行表结构设计
- 维护优化:根据实际情况对索引、存储结构等进行优化
数据库结构优化的目的
- 减少数据冗余
- 尽量你变数据维护中出现更新,插入和删除异常
- 简约数据库的存储空间
- 提高查询效率
为了设计出没有数据冗余和数据维护异常的数据结构,我们需要遵循以下规范:
- 第一范式
- 数据库表中的所有字段都只有单一属性
- 单一属性的列都是由基本的数据类型所构成
- 设计出来的表都是简单的二维表
- 第二范式 要求一个表中只具有一个业务主键,也就是说符合第二范式的表中不能存在非主键列对只对部分主键的依赖关系。以学生选课为例,它的主键是复合主键(学生编号,课程),而学分只依赖于课程,即非主键列只对部分主键存在依赖关系,不符合第二范式。
针对这个问题,我们怎么破呢?我们对上面这个表拆分为3个表:学生表、课程表、学生课程关系表。其中,学生表和课程表只有一个主键,而学生课程关系表有一个复合主键(学生编号,课程),分数完全依赖于这个复合主键,因此符合第二范式。
第三范式
每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主属性对主键的传递依赖。 对于学生表,学院依赖于学生编号,而学院地址却依赖于学院,这就是传递依赖,此时,这张表不满足第三范式。如果想让这张表满足第三范式就需要继续对这张表进行拆分。
反范式化
遵循范式化的数据库设计,实现了消除数据冗余的目的,但是此时数据库的性能和读取效率并不是最优的。为了性能和读取效率的考虑而适当的对数据库设计范式的要求进行违反,而允许存在少量的数据冗余,换句话来说反范式化就是使用空间来换取时间。 举个栗子,以我们经常进行下单为例。根据范式准则,定单表和订单商品关联表如下:
订单表:{订单编号,下单用户名,下单日期,支付金额,物流单号}
订单商品关联表:{订单编号,订单商品分类,订单商品名,商品数量}
我们知道查询订单时,往往需要知道用户名称和用户手机号,那么,此时我们就需要将订单表和用户表进行关联查询。这种设计存在一个问题,当用户修改手机号,那么用旧手机号买的订单号的手机信息是新的手机号,而不是旧手机号,这是不符合业务需求的。解决这个问题的办法就是将用户名和用户手机号加入到订单表中。同样情况,商品的价格也存在修改的情况,因此,也需要将支付金额加入到订单表中,此时,订单表和订单商品关联表如下:
订单表:{订单编号,下单用户名,下单日期,支付金额,物流单号,订单金额}
订单商品关联表:{订单编号,订单商品分类,订单商品名,商品数量,商品单价}
总结
- 范式化设计可以尽量的减少数据冗余,更新操作比反范式化更快,但是对于查询需要对多个表进行关联,更难进行索引优化。
- 反范式化设计可以减少表的关联(顺序IO),可以更好的进行索引优化,但是存在数据冗余及数据维护异常,对数据的修改需要更多的成本(需要修改多个地方)。 因此,我们需要结合反范式化和范式化,设计出高性能数据库结构。
欢迎关注微信公众号:木可大大,所有文章都将同步在公众号上。
- Numpy教程第1部分 - 阵列简介(常用基础操作总结)
- Session和Cookies的基本原理
- 浅析Numpy.genfromtxt及File I/O讲解
- 损失函数详解
- 排查Java的内存问题
- 使用两种方法让 ASP.NET Core 实现遵循 HATEOAS 结构的 RESTful API
- 设计模式六大原则(5):迪米特法则
- Selenium2+python自动化61-Chrome浏览器(chromedriver)
- 区块链可以减少社会不平等吗?
- 【干货】不止准确率:为分类任务选择正确的机器学习度量指标(附代码实现)
- python爬虫beautifulsoup4系列1
- 区块链入门教程
- python爬虫beautifulsoup4系列2
- python爬虫beautifulsoup4系列3
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 62. Vue 饿了么Mint UI组件的基本使用
- 【colab pytorch】数据处理
- requests+lxml+xpath爬取豆瓣电影
- python之子类继承父类时进行初始化的一些问题
- 【猫狗数据集】定义模型并进行训练模型
- springmvc之处理模型数据Map
- requests+lxml+xpath爬取电影天堂
- 【python-leetcode90-子集】子集Ⅱ
- 【colab pytorch】保存模型
- 【猫狗数据集】保存训练模型并加载进行继续训练
- django-URL匹配(二)
- opengl-球体的绘制
- 【python-leetcode46-子集】全排列
- 【python-leetcode784-子集】字母大小写全排列
- 悬挂引用是如何被Rust消灭的?