数据库表设计,三大范式是什么?

2024-08-28 21:36
文章标签 设计 三大 数据库 范式

本文主要是介绍数据库表设计,三大范式是什么?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据库表设计 三大范式是什么?

  • 前言
  • 第一范式
  • 第二范式
  • 第三范式
  • 反范式设计
  • 数据表的设计原则总结
  • 库表设计理念建议
    • 关于库
    • 关于表、列

前言

公司新项目现在是从0到1设计,不知道怎么数据库设计交给了我和同桌两个人。明确需求之后我两就开始设计数据库表了。MySQL中说数据库设计需要遵守三大范式,今天顺便看看这三范式是什么东西。

首先在设计表之前,需要对需求进行抽象,将需求抽象为业务实体,实体对应着数据库中的表,实体属性就是表中的字段。要想设计—个好的关系,必须使关系满足一定的约束条件,此约束已经形成了规范,分成几个等级,一级比一级要求得严格。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,数据库只需满足第三范式(3NF)就行了。所以我们下面来细说以下三范式

第一范式

第一范式要求表中的字段不能继续拆分,满足原子性字段。

比如创建用户表,包含id和name-age字段,这是万万不可的,name和id不符合第一范式,应该将其拆分为2个字段。

字段的原子性对于我们设计者来说是主观的,例如一个住址信息的字段,我住在上海市徐汇区xx街道xx路xx号,是否需要把住址信息拆分到省、市、区、街道、路呢? 对于不同的场景,划分是不一样的。我记得在填报国企面试的时候,这些字段都是拆分开填的,那么对应的存在他们国企数据库中的,也是分开的。

第二范式

第二范式是在第一范式基础上简历起来的,要想满足第二范式,必须要先满足第一范式。

第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。也就是实体都是通过主键区分的,并且是完全依赖这个主键,不能依赖主键的一部分。

eg:比赛表中包含球员编号,姓名,年龄,比赛编号,比赛时间,比赛场地等属性

(球员编号,比赛编号)->(姓名,年龄,比赛时间,比赛场地,得分)

如果设计(球员编号,比赛编号)为主键,可以看到字段(姓名,年龄)完全依赖(球员编号),而不是(球员编号,比赛编号),只依赖了主键(球员编号,比赛编号)的一部分,同理(比赛时间,比赛场地)也是如此。

这样的表会发生很严重的数据冗余:

  1. 如果球员参加m场比赛,球员姓名和年龄就重复了m-1次,比赛有n个球员参加,比赛时间和场地也重复了n-1次

同时 如果想要插入一场新的比赛,球员还没确定,增加不了数据;某个球员退役想要删除这个球员编号,那么他的比赛信息也会都删除掉。

所以通常来说,我们会设计出三张表

  1. 球员表 球员编号+姓名+年龄
  2. 比赛表 比赛编+比赛时间+比赛场地
  3. 球员比赛关系表 球员编号+比赛编号+得分

这样设计就符合第二范式了,实体完全依赖并只依赖主键,而非依赖主键的部分。

第三范式

第三范式把第二范式更加细化,第二范式强调的是实体依赖于主键,通过主键区分一个个实体,第三范式强调实体中的其他非主键键只依赖于这个主键。

例如:

部门信息表:部门编号,部门名称,部门简介

员工信息表:员工编号,姓名,部门编号

当员工信息表中有了部门编号后,就不必再写部门名称,部门简介这种信息了,否则会存在很多数据冗余。

另一个例子:

如下的商品表,不符合第三范式,其中商品类别名称还强依赖于商品类别id

img

应该设计为两张独立的表:通过category_id进行关联

img

img

反范式设计

完全符合范式化的设计并非完美,很多实际业务中其实本来就是存在大量数据冗余的,因为表关联对于查询性能的影响更加严重。

反范式设计就是为了性能和读取效率而适当违反范式规范,允许存在冗余字段,用空间换时间。

例如上述的商品表中冗余存储商品类别名称,在查询的时候,直接就把商品和商品类别名称查出来了,不用关联单独的商品类别表查出这个数据。

img

反范式的优缺点:

  1. 优点

    1. 减少表关联,提高查询速度
    2. 更好的进行索引优化,因为表关联会带来索引失效。
  2. 缺点

    1. 有冗余字段,空间变大
    2. 一个表中修改值,冗余表也要修改,否则数据不一致
    3. 数据量小的时候,表关联带来的查询损耗很小,反范式不能体现出优势,还会让数据库设计复杂化

数据表的设计原则总结

  1. 数据表的个数越少越好
  2. 数据表中的字段个数越少越好
  3. 数据表中联合主键的字段个数越少越好
  4. 使用主键和外键越多越好

库表设计理念建议

关于库

  1. 【强制】库的名称必须控制在32个字符以内,只能使用英文字母、数字和下划线,建议以英文字
    母开头。
  2. 【强制】库名中英文 一律小写 ,不同单词采用 下划线 分割。须见名知意。
  3. 【强制】库的名称格式:业务系统名称_子系统名。
  4. 【强制】库名禁止使用关键字(如type,order等)。
  5. 【强制】创建数据库时必须 显式指定字符集 ,并且字符集只能是utf8或者utf8mb4。
    创建数据库SQL举例:CREATE DATABASE crm_fund DEFAULT CHARACTER SET ‘utf8’ ;
  6. 【建议】对于程序连接数据库账号,遵循 权限最小原则
    使用数据库账号只能在一个DB下使用,不准跨库。程序使用的账号 原则上不准有drop权限 。
  7. 【建议】临时库以 tmp_ 为前缀,并以日期为后缀;
    备份库以 bak_ 为前缀,并以日期为后缀。

关于表、列

  1. 【强制】表和列的名称必须控制在32个字符以内,表名只能使用英文字母、数字和下划线,建议
    以 英文字母开头 。
  2. 【强制】 表名、列名一律小写 ,不同单词采用下划线分割。须见名知意。
  3. 【强制】表名要求有模块名强相关,同一模块的表名尽量使用 统一前缀 。比如:crm_fund_item
  4. 【强制】创建表时必须 显式指定字符集 为utf8或utf8mb4。
  5. 【强制】表名、列名禁止使用关键字(如type,order等)。
  6. 【强制】创建表时必须 显式指定表存储引擎 类型。如无特殊需求,一律为InnoDB。
  7. 【强制】建表必须有comment。
  8. 【强制】字段命名应尽可能使用表达实际含义的英文单词或 缩写 。如:公司 ID,不要使用
    corporation_id, 而用corp_id 即可。
  9. 【强制】布尔值类型的字段命名为 is_描述 。如member表上表示是否为enabled的会员的字段命
    名为 is_enabled。
  10. 【强制】禁止在数据库中存储图片、文件等大的二进制数据
    通常文件很大,短时间内造成数据量快速增长,数据库进行数据库读取时,通常会进行大量的随
    机IO操作,文件很大时,IO操作很耗时。通常存储于文件服务器,数据库只存储文件地址信息。
  11. 【建议】建表时关于主键: 表必须有主键 (1)强制要求主键为id,类型为int或bigint,且为
    auto_increment 建议使用unsigned无符号型。 (2)标识表里每一行主体的字段不要设为主键,建议
    设为其他字段如user_id,order_id等,并建立unique key索引。因为如果设为主键且主键值为随机
    插入,则会导致innodb内部页分裂和大量随机I/O,性能下降。
  12. 【建议】核心表(如用户表)必须有行数据的 创建时间字段 (create_time)和 最后更新时间字段
    (update_time),便于查问题。
  13. 【建议】表中所有字段尽量都是 NOT NULL 属性,业务可以根据需要定义 DEFAULT值 。 因为使用
    NULL值会存在每一行都会占用额外存储空间、数据迁移容易出错、聚合函数计算结果偏差等问
    题。
  14. 【建议】所有存储相同数据的 列名和列类型必须一致 (一般作为关联列,如果查询时关联列类型
    不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)。
  15. 【建议】中间表(或临时表)用于保留中间结果集,名称以 tmp_ 开头。
    备份表用于备份或抓取源表快照,名称以 bak_ 开头。中间表和备份表定期清理。

这篇关于数据库表设计,三大范式是什么?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115947

相关文章

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

MySQL MHA集群详解(数据库高可用)

《MySQLMHA集群详解(数据库高可用)》MHA(MasterHighAvailability)是开源MySQL高可用管理工具,用于自动故障检测与转移,支持异步或半同步复制的MySQL主从架构,本... 目录mysql 高可用方案:MHA 详解与实战1. MHA 简介2. MHA 的组件组成(1)MHA

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE

通过DBeaver连接GaussDB数据库的实战案例

《通过DBeaver连接GaussDB数据库的实战案例》DBeaver是一个通用的数据库客户端,可以通过配置不同驱动连接各种不同的数据库,:本文主要介绍通过DBeaver连接GaussDB数据库的... 目录​一、前置条件​二、连接步骤​三、常见问题与解决方案​1. 驱动未找到​2. 连接超时​3. 权限不

MySQL数据库读写分离与负载均衡的实现逻辑

《MySQL数据库读写分离与负载均衡的实现逻辑》读写分离与负载均衡是数据库优化的关键策略,读写分离的核心是将数据库的读操作与写操作分离,本文给大家介绍MySQL数据库读写分离与负载均衡的实现方式,感兴... 目录读写分离与负载均衡的核心概念与目的读写分离的必要性与实现逻辑读写分离的实现方式及优缺点读负载均衡

Go语言中如何进行数据库查询操作

《Go语言中如何进行数据库查询操作》在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三... 查询函数QueryRow和Query详细对比特性QueryRowQuery返回值数量1个:*sql

Mysql数据库聚簇索引与非聚簇索引举例详解

《Mysql数据库聚簇索引与非聚簇索引举例详解》在MySQL中聚簇索引和非聚簇索引是两种常见的索引结构,它们的主要区别在于数据的存储方式和索引的组织方式,:本文主要介绍Mysql数据库聚簇索引与非... 目录前言一、核心概念与本质区别二、聚簇索引(Clustered Index)1. 实现原理(以 Inno

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代