👀业务数据库设计流程
-
需求分析
:根据用户的需求,分析出需要记录的数据 -
概要设计
:根据分析出的数据,设计 ER 图- er 图是比较抽象的,图里面只说明了每个实体具有什么属性。比如用户名,但是它的数据类型、有无约束都不会在 er 图上出现。
-
详细设计
:将 er 图转换成数据库模型图和数据表
👀瀑布模型还是螺旋模型?
💡什么是瀑布模型?
- 适合瀑布模型的前提是:
- 有非常明确的需求
- 用户不会在中途修改需求
- 但是现在的一些企业,都没有一个明确的需求,什么火做什么。面对这种不确定的需求,不应该使用瀑布模型。适合使用螺旋模型
💡什么是螺旋模型?
螺旋模型(Spiral Model)是一种软件开发生命周期模型,由 Barry Boehm 在 1986 年提出。它结合了迭代开发模型的特点和系统性的风险管理方法。螺旋模型特别强调风险分析,适用于大型、复杂、高风险的项目。
螺旋模型的基本特点和过程如下:
- 四个主要阶段:螺旋模型由四个主要阶段组成,这四个阶段在每次迭代中都会被重复。这些阶段是:计划、风险分析、工程/开发、以及客户评估。
- 迭代开发:与传统的水瀑布模型不同,螺旋模型通过多次迭代来开发软件。每次迭代都像一个螺旋的圈,而项目进展时就像螺旋的上升。
- 风险管理:在每次迭代中,都会进行风险分析。这使得项目团队可以及时识别和应对潜在的问题,从而减少项目失败的风险。
- 客户反馈:在每次迭代的最后,都会有一个原型或部分完成的系统提交给客户以获取反馈。这确保了客户的需求得到满足,并使软件开发更加灵活和响应迅速。
优点:
- 强调风险管理,可以及时识别和处理风险。
- 由于其迭代性质,更容易适应需求变化。
- 客户持续参与,确保了需求的满足。
缺点:
- 可能导致项目周期的延长,因为需要反复进行风险分析和客户评估。
- 需要经验丰富的项目团队来识别和处理风险。
- 可能增加项目的成本,因为需要进行多次迭代和评估。
总体上,螺旋模型是一个灵活的开发方法,特别适合于大型和高风险的项目。但它也要求项目团队具有高度的专业知识和经验。
👀如何看懂 ER 图
💡什么是 ER 图?
-
ER 也称 实体关系图(Entity Relationship Diagram),提供了表示实体类型、属性和关系的方法,用来描述现实世界的概念模型。
-
ER 图的基本元素:
- 实体(Entity):通常用矩形表示。
- 关系(Relationship):通常用菱形表示。
- 属性(Attribute):通常用椭圆表示。
-
如上图,含义如下:
- 矩形:表示实体
- 椭圆形:表示字段
- 主键:在字段上使用下划线
- 菱形:外键约束
💡ER 图与用例图对比
-
左侧是 ER 图,有过多个实体,实体之间还有关系。
-
右侧是用例图,表现的是 用户和功能之间的关系。
-
ER 图
:重点在于表示数据的结构和关系。它展示了数据对象(实体)如何与其他对象相关联。 -
用例图
:是 UML 中的一种图,主要描述系统的功能和用户如何与这些功能互动。它重点在于系统的行为和功能,而不是数据结构。 -
简而言之,ER 图关注“数据是什么”,而用例图关注“系统做什么”。
💡绘制 ER 图的软件
- Office Visio、Office Word:专业庞大
- 亿图图示(Edraw):小巧好用
- Enterprise Architect(EA):老牌软件,中文本地化不好,不适合小白使用
💡ER 图属性语法
✍复合属性:是多个属性的组合
- 工号是由多个属性组合而成的。
✍多值属性:是某个属性可以有多多个不同的取值;用双线椭圆表示
- 比如一个员工拥有多个角色,这个角色就是多值属性,使用双椭圆表示。再比如,一个员工有多个联系电话号码等类似的属性
- 在设计数据库字段时,最简单的是定义为 varchar,用逗号分隔数据存储。也或则说用 MySQL 新的数据类型 JSON 来存储。
✍派生属性:是不保存在实体中的属性;用虚线的椭圆表示
- 简单说,派生属性是运算的结果。比如分页中的总数,是计算出来的。如下图中的人数
✍可选属性:是允许没有值的属性;在字段下使用(0) 表示
- 比如备注属性。
💡实体关系语法
✍1 对 1
- 一个员工可以领取一台办公电脑,使用 菱形关联 1 对 1
✍1 对 N
✍N 对 N
- ER 图示概要设计阶段的产物,进入详细设计阶段,我们要把 ER 图转换为模型图。
名称 | 作用 | 使用场景 | 优点 | 缺点 |
---|---|---|---|---|
第一范式 (1NF) | 📦 数据表的每一列都是不可分割的最小单元,每一列都有唯一的名称。 | ⚙️ 所有关系型数据库设计的开始 | ✅确保每一列数据的原子性,简化数据结构 | 🚫可能导致数据冗余 |
第二范式 (2NF) | 📦满足1NF,并且表中的非主键列都完全依赖于主键。 | 🔑 当数据表有复合主键(由多个字段组成)时 | ✅减少数据冗余和冗余存储,提高数据完整性 | 🚫可能需要更多的表连接,可能影响性能 |
第三范式 (3NF) | 📦满足2NF,并且非主键列之间没有相互依赖关系。 | ⚙️ 所有关系型数据库设计 | ✅进一步减少数据冗余,确保数据的独立性和完整性 | 🚫可能导致更多的表和连接,可能复杂化查询 |
反范式 | 🔄故意引入冗余数据,通过减少表连接来优化查询性能。 | 🚀 数据仓库、读密集型应用、需要高性能查询的场景 | ✅提高查询性能,减少表连接的复杂性和成本 | 🚫增加数据冗余,可能导致数据更新和维护的复杂性 |
👀范式和反范式
💡范式的优点和缺点
优点:
- 🚀更新速度:范式化的更新操作通常比反范式化要快,因为只有很少或没有重复数据,所以只需要修改更少的数据。
- 🧠内存使用:范式化的表通常更小,可以更好地放在内存里,从而加快执行操作。
- 🛡️数据一致性:范式化减少了数据冗余,从而降低了数据不一致的风险。
- 🔍简化查询:由于数据不重复,查询列表数据时往往不需要使用
DISTINCT
或GROUP BY
语句。
缺点:
- 🔗需要更多的关联:范式化设计的 schema 往往需要更多的表关联,这可能导致查询变得复杂且代价昂贵。
- 🚫索引局限性:由于数据分散在多个表中,可能无法创建涵盖多个表的复合索引。
💡反范式的优点和缺点
优点:
- 🔗避免关联:反范式化的 schema 由于数据集中,可以避免表关联,从而简化查询。
- 🚀性能优势:对于某些查询,全表扫描可能比多表关联更快,尤其是当数据量大而内存有限时。
- 🔍灵活的索引:数据集中在一张表中,可以创建更多种类的索引,提高查询效率。
缺点:
- 🚫数据冗余:可能导致数据更新、删除和插入的复杂性增加。
- ⚠️数据不一致风险:由于数据冗余,如果不同位置的相同数据没有同步更新,可能导致数据不一致。
💡混用范式化和反范式化
在实
际的数据库设计中,通常需要根据实际应用的需要,权衡范式化和反范式化的优缺点,进行适当的混合使用。例如,可以将经常一起查询的数据存储在同一张表中,而将不经常变动的数据进行范式化。
策略:
- 🔄数据复制或缓存:在不同的表中存储相同的某些列,利用MySQL的触发器功能来同步更新。
- 🔝排序需求:为了满足排序需求,可以从父表冗余一些数据到子表。
总结:
🌈范式化和反范式化都有其适用的场景,需要根据应用的实际需求进行选择。正确的策略是在保证数据一致性的前提下,通过合理的设计提高查询效率。
👀常见的设计模式
名称 | 作用 | 使用场景 | 优点 | 缺点 |
---|---|---|---|---|
规范化模式 | 🔄 通过消除数据冗余和确保数据完整性来组织数据 | ⚙️ 通用关系型数据库设计 | ✅ 减少数据冗余,提高数据完整性和一致性 | 🚫 可能需要更多的表连接,可能影响性能 |
宽表模式 | 📊 单一表中包含大量列 | 🔍 需要在单次查询中检索大量相关信息 | ✅ 简化查询,避免多表连接 | 🚫 可能导致数据冗余,性能问题,难以维护 |
垂直分割 | 📏 将一个表的列分割到多个表中 | ⚖️ 当某些列被频繁查询,而其他列不是 | ✅ 优化查询性能,减少读取不必要数据的开销 | 🚫 增加了数据管理的复杂性 |
归档和分区 | 📦 将表的数据分成多个分区或归档旧数据 | 🕰️ 大型表,历史数据存储 | ✅ 提高查询性能,简化数据维护 | 🚫 增加了数据管理的复杂性 |
关联表模式 | 🔗 存储多对多关系 | 🌐 需要表示和查询多对多的关系 | ✅ 灵活地表示多对多关系 | 🚫 增加了数据管理和查询的复杂性 |
EAV模式 | 🧩 存储灵活、动态或稀疏属性 | 🔧 动态属性,配置数据,元数据存储 | ✅ 非常灵活,可以存储不规则数据结构 | 🚫 查询复杂,性能可能较差,难以维护 |
规范化模式:
- 在设计关系型数据库时,通常首先考虑规范化模式,因为它可以确保数据的完整性和减少冗余。
宽表模式:
- 当需要在单个查询中检索大量相关信息时,宽表模式是有用的。它可以避免多表连接,从而提高查询性能。
垂直分割:
- 垂直分割是在数据列被不均匀地访问时的一种策略,例如,某些列被频繁地查询,而其他列则不是。
归档和分区:
- 对于大型表,可以考虑分区策略,以提高查询性能。另外,旧的不常用数据可以归档,以减少存储和维护成本。
关联表模式:
- 关联表模式是表示多对多关系的标准方法。它提供了灵活性,但也增加了查询和数据管理的复杂性。
EAV模式:
- EAV模式非常灵活,可以存储不规则或动态的数据结构,但它也带来了查询和维护的挑战。
👀设计中的陷阱
💡太多的列
- ⚠️ 在数据库表中添加太多的列可能会导致性能问题,尤其是当只有少数列被频繁使用时。
建议🛠️: 仔细考虑每个列的用途,避免添加不必要的列,尤其是在读取性能至关重要的情况下。
💡太多的关联
- ⚠️ 大量的表关联会导致查询复杂性增加,进而影响性能。虽然在某些情况下多表关联是必要的,但过度使用可能导致问题。
建议🛠️: 在设计数据库模式时,考虑查询的最常见用例,并尽量简化需要的关联。
💡全能的枚举
- ⚠️ 虽然枚举类型可以确保数据的完整性,但它也带来了维护上的挑战,特别是在需要修改可能的值时。
建议🛠️: 评估枚举类型的真正需求,并考虑使用其他更灵活的数据类型。
💡变相的枚举
- ⚠️ 集合数据类型在某些情况下可能很有用,但在其他情况下可能导致数据模型的复杂性。
建议🛠️: 在选择使用集合数据类型之前,仔细考虑其优缺点,确保它真的适合你的需求。
💡非此发明(Not Invent Here)的 NULL
- ⚠️ 虽然NULL有其用途,但它也会增加查询的复杂性,并在某些情况下导致不明确的结果。
建议🛠️: 在设计数据库模式时,考虑数据的实际意义,并确保为每个字段选择最适合的默认值。
👀如何选择数据类型
💡如何选择数据类型
💼 推荐的
推荐事项 | 优点 | 缺点 |
---|---|---|
🔍 优先选择最小数据类型 符合存储数据需求 | 1. 节省存储空间 2. 更快的查询性能 3. 数据完整性提高 | 可能会限制未来的数据扩展性 |
📌 简单数据类型 如整型优于字符类型 | 1. 较少的CPU周期 2. 更好的性能 3. 适合索引和聚合操作 | 字符集和排序可能增加字符比较的复杂性 |
❌ 避免NULL 除非真的需要存储NULL值 | 1. 更容易优化 2. 节省存储空间 3. 简化索引、统计和值比较 | 特定情况下可能需要NULL,如InnoDB中的稀疏数据 |
⚠️ 谨慎使用 ENUM、TEXT 字符串类型 | 1. ENUM 提供数据完整性2. TEXT 适用于大量文本数据 | 1. ENUM 修改困难,可能导致表重建2. TEXT 可能导致性能问题 |
💰 财务数据使用 decimal 类型避免浮点误差 | 1. 金融数据精确性 2. 避免浮点数近似误差 | 相比其他数值类型,可能需要更多存储空间 |
💼 总体的
数据类型 | 描述 | 优点 | 缺点 | 使用场景 |
---|---|---|---|---|
🔢 整数类型 | 存储整数值 | - 小存储空间需求 - 优越的计算性能 - 适合索引和聚合操作 | - 无法存储小数 - 范围限制,不适合超大值 | 用户ID、订单数量、年龄 |
🔍 浮点数类型 | 存储小数值 | - 可存储小数 - 计算速度快 - 适用于科学和工程计算 | - 有精度限制,可能有误差 - 不适合精确金融计算 | 产品价格、温度、经纬度 |
💰 定点数类型 | 存储精确小数值 | - 精确存储小数 - 适合精确金融和货币计算 | - 更多存储空间需求 - 计算速度可能慢 | 金融交易、货币、百分比 |
📅 日期时间类型 | 存储日期时间信息 | - 方便日期计算 - 时区和日期函数支持 | - 额外存储空间需求 - 时区处理可能复杂 | 订单日期、注册时间、时间戳 |
📝 字符串类型 | 存储文本数据 | - 适用于各种文本信息 - 可以指定长度或使用可变长 - 支持字符串函数 | - CHAR可能浪费空间 - VARCHAR可能导致数据截断 - 查询可能慢 | 用户名、产品描述、文章内容 |
📚 文本类型 | 存储大文本数据 | - 适用于大文本,如博客 - 可存储大量字符 | - 需要更多存储空间 - 查询大文本可能慢 | 博客、评论、文章内容 |
🖼️ 二进制类型 | 存储二进制数据 | - 适用于图像、文件等 - 适合存储多媒体文件 | - 需要更多存储空间 - 不适合文本搜索 | 用户头像、文件、图像 |
🔘 枚举和集合类型 | 存储固定或多选选项 | - 提供数据约束 - 适用于有限选项 - 枚举适用于单选,集合适用于多选 | - 不适合存储大量不同选项 - 不支持动态选项,需手动管理 | 用户角色、产品标签、颜色 |
🌍 空间数据类型 | 存储地理或几何数据 | - 适用于GIS分析 - 支持空间查询和分析 - 多种子类型 | - 需要更多存储空间 - 查询和分析需要专业知识和工具 | 地理位置、地图数据 |
📜 JSON 数据类型 | 存储JSON格式数据 | - 可存储复杂结构数据 - 适用于半结构化数据 - 支持JSON查询语法 | - 不适合关系型查询 - 需要额外解析和处理 | 配置、日志、应用状态 |
💡如何为表和列选择合适的名字
步骤 | 描述 |
---|---|
1️⃣ | 业务需求调研 |
2️⃣ | 面向对象设计 |
3️⃣ | 范式化设计 |
4️⃣ | 反范式化设计 |
5️⃣ | 物理设计 (硬件) |
6️⃣ | 数据类型选择 |
7️⃣ | 对象命名 |
📌 所有对象名称必须使用小写字母,可选用下划线分割 | |
🚫 避免使用MySQL保留关键字,参考官方手册 | |
🎯 对象名称要见名知义,最好不超过32个字符 | |
🔍 临时库表应以"tmp"为前缀并以日期为后缀 | |
💾 用于备份的库表应以"bak"为前缀并以日期为后缀 | |
8️⃣ | 保持列名和列类型的一致性 |