数据建模Skill data-modeling

数据建模是设计数据库模式、数据仓库和数据分析系统的核心技能,涵盖维度建模、星型模式、数据保险库等技术,用于优化数据存储和查询性能,支持操作型和分析型数据处理。关键词:数据建模,数据库设计,数据仓库,OLAP,OLTP,维度建模,星型模式,数据保险库。

数据工程 0 次安装 0 次浏览 更新于 3/11/2026

name: data-modeling description: 用于设计数据模型、数据库模式或选择建模方法时使用。涵盖维度建模、星型模式、数据保险库、实体-关系设计和模式演进。 allowed-tools: Read, Glob, Grep

数据建模

操作数据库、数据仓库和分析系统的数据建模技术综合指南。

何时使用此技能

  • 设计数据库模式
  • 选择建模方法
  • 构建数据仓库
  • 规划模式演进
  • 理解数据模型中的权衡
  • 为分析vs操作设计

数据建模基础

数据模型类型

数据模型类别:

1. 概念模型
   目的: 业务理解
   受众: 业务利益相关者
   内容: 实体、关系、业务规则
   细节: 高层次,无实现细节

2. 逻辑模型
   目的: 结构定义
   受众: 数据架构师
   内容: 表、列、键、关系
   细节: 数据库无关设计

3. 物理模型
   目的: 实现
   受众: 数据库工程师
   内容: 索引、分区、存储
   细节: 数据库特定优化

模型演进:
┌─────────────────────────────────────────────────────────────┐
│                                                              │
│  业务需求        概念模型        逻辑模型        物理模型   │
│  Business       Conceptual      Logical       Physical      │
│  Requirements ──► Model     ──► Model    ──► Model         │
│                                                              │
│  "客户下订单"    客户 ─────►  customers    customers        │
│                 订单          ├── id        ├── id PK       │
│                  └──< 下单     ├── name      ├── name        │
│                                └── email     ├── email       │
│                                              └── idx_*       │
│                                                              │
└─────────────────────────────────────────────────────────────┘

操作型 vs 分析型

操作型 (OLTP) vs 分析型 (OLAP):

┌────────────────────────────────────────────────────────────┐
│                      OLTP                                   │
│            (在线事务处理)                                   │
├────────────────────────────────────────────────────────────┤
│ 目的:     运行业务                                          │
│ 负载:     多个小事务                                        │
│ 模型:     规范化 (3NF)                                      │
│ 优化:     写入性能,一致性                                  │
│ 用户:     应用,服务                                        │
│ 示例:     插入新订单,更新库存                              │
└────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────┐
│                      OLAP                                   │
│            (在线分析处理)                                   │
├────────────────────────────────────────────────────────────┤
│ 目的:     分析业务                                          │
│ 负载:     少量复杂查询                                      │
│ 模型:     反规范化 (星型/雪花型)                            │
│ 优化:     读取性能,聚合                                    │
│ 用户:     分析师,BI工具                                    │
│ 示例:     按区域、月汇总销售额                              │
└────────────────────────────────────────────────────────────┘

何时使用:
├── OLTP: 面向用户的应用程序,实时操作
├── OLAP: 报告,仪表板,机器学习
└── 混合: 某些系统需要两者 (HTAP)

规范化

范式

数据库规范化:

1NF (第一范式):
├── 消除重复组
├── 为相关数据创建单独表
├── 用主键标识每一行
└── 每个单元格包含单一值

示例 (SQL Server - PascalCase):
❌ Orders (Id, Item1, Item2, Item3)
✓ Orders (Id, ...) + OrderItems (OrderId, ItemId)

2NF (第二范式):
├── 满足1NF要求
├── 移除部分依赖
└── 非键列依赖于整个主键

示例 (SQL Server - PascalCase):
❌ OrderItems (OrderId, ProductId, ProductName)
✓ OrderItems (OrderId, ProductId) + Products (ProductId, ProductName)

3NF (第三范式):
├── 满足2NF要求
├── 移除传递依赖
└── 非键列仅依赖于主键

示例 (SQL Server - PascalCase):
❌ Orders (Id, CustomerId, CustomerCity)
✓ Orders (Id, CustomerId) + Customers (Id, City)

BCNF (Boyce-Codd范式):
├── 满足3NF要求
├── 每个决定子都是候选键
└── 处理多值依赖

更高范式 (4NF, 5NF):
├── 处理复杂多值依赖
├── 实践中很少使用
└── 可能导致过度规范化

何时反规范化

规范化权衡:

规范化 (3NF):
├── 优点: 数据完整性,无冗余,存储较小
├── 缺点: 复杂连接,读取较慢
└── 使用: OLTP,写密集型负载

反规范化:
├── 优点: 读取更快,查询更简单
├── 缺点: 冗余,更新异常,存储较大
└── 使用: OLAP,读密集型负载

反规范化触发点:
1. 读取性能关键
2. 写入频率低
3. 数据变更不频繁
4. 查询频繁连接相同表
5. 聚合常见

受控反规范化模式:
┌─────────────────────────────────────────────────────────────┐
│ 模式: 汇总表                                                │
│ 保持规范化 + 物化聚合                                       │
│                                                              │
│  orders ──┐                                                 │
│  items  ──┼──► daily_sales_summary (物化)                  │
│  products─┘                                                 │
│                                                              │
│ 两者兼得: 写入规范化,从汇总读取                            │
└─────────────────────────────────────────────────────────────┘

维度建模

星型模式

星型模式:
中心事实表周围围绕维度表。

                    ┌──────────────┐
                    │  dim_date    │
                    │──────────────│
                    │ date_key  PK │
                    │ date         │
                    │ month        │
                    │ quarter      │
                    │ year         │
                    └──────┬───────┘
                           │
┌──────────────┐    ┌──────┴───────┐    ┌──────────────┐
│ dim_product  │    │  fact_sales  │    │ dim_customer │
│──────────────│    │──────────────│    │──────────────│
│ product_key PK│◄──│ date_key  FK │───►│ customer_key PK│
│ product_name │    │ product_key FK│    │ customer_name│
│ category     │    │ customer_key FK│   │ segment      │
│ brand        │    │ store_key  FK │    │ region       │
└──────────────┘    │──────────────│    └──────────────┘
                    │ quantity     │
                    │ revenue      │           │
                    │ cost         │           │
                    └──────┬───────┘    ┌──────┴───────┐
                           │            │  dim_store   │
                           └───────────►│──────────────│
                                       │ store_key  PK│
                                       │ store_name   │
                                       │ city         │
                                       │ state        │
                                       └──────────────┘

星型模式优点:
├── 简单查询 (少连接)
├── 优化聚合
├── 对业务用户直观
├── 与BI工具配合良好
└── 可预测查询性能

事实表类型:
├── 事务型: 每个事件一行 (销售,点击)
├── 周期性快照: 每个周期一行 (日余额)
├── 累积快照: 跟踪进度 (订单生命周期)
└── 无度量事实: 无度量事件 (出席)

雪花型模式

雪花型模式:
规范化维度 (维度有子维度)。

                    ┌──────────────┐
                    │  dim_date    │
                    └──────┬───────┘
                           │
┌──────────────┐    ┌──────┴───────┐    ┌──────────────┐
│ dim_category │◄───│ dim_product  │    │ dim_customer │
└──────────────┘    └──────┬───────┘    └──────┬───────┘
                           │                    │
        ┌──────────────────┼────────────────────┼──────┐
        │           ┌──────┴───────┐            │      │
        │           │  fact_sales  │            │      │
        │           └──────┬───────┘            │      │
        │                  │                    │      │
        │           ┌──────┴───────┐     ┌──────┴──────┐
        │           │  dim_store   │     │ dim_segment │
        │           └──────┬───────┘     └─────────────┘
        │                  │
        │           ┌──────┴───────┐
        │           │  dim_city    │
        │           └──────────────┘

星型 vs 雪花型:
┌────────────────────────────────────────────────────────────┐
│ 因素          │ 星型              │ 雪花型                │
├─────────────────┼───────────────────┼──────────────────────┤
│ 查询简单性│ 更简单           │ 更复杂                 │
│ 查询速度     │ 更快 (连接少)    │ 更慢                  │
│ 存储         │ 更多 (冗余)     │ 更少 (规范化)         │
│ 维护         │ 更容易          │ 更复杂                │
│ BI工具支持 │ 更好            │ 可能需要建模          │
└────────────────────────────────────────────────────────────┘

推荐: 优先星型模式,除非存储是关键问题。

缓慢变化维度

缓慢变化维度 (SCD):
如何处理维度随时间变化。

类型 0: 保留原始
└── 从不更新维度
└── 用于: 不应更改的属性

类型 1: 覆盖
└── 就地更新,丢失历史
└── 用于: 纠正,非历史属性

类型 2: 添加新行 (最常见)
┌─────────────────────────────────────────────────────────────┐
│ customer_key│ customer_id │ address      │ valid_from │ valid_to │ current│
├─────────────┼─────────────┼──────────────┼────────────┼──────────┼────────┤
│ 1001        │ C123        │ 123 Oak St   │ 2020-01-01 │ 2023-06-30│ false  │
│ 1002        │ C123        │ 456 Pine Ave │ 2023-07-01 │ 9999-12-31│ true   │
└─────────────────────────────────────────────────────────────┘
└── 新代理键,跟踪有效期间
└── 用于: 需要完整历史

类型 3: 添加新列
└── 先前和当前值列
└── 用于: 有限历史 (仅先前)

类型 4: 历史表
└── 主表中当前,历史在单独表
└── 用于: 频繁变更,大维度

类型 6: 混合 (1+2+3)
└── 结合方法以获得灵活性
└── 用于: 复杂需求

数据保险库

数据保险库架构

数据保险库建模:
企业数据仓库模式,用于敏捷性和可审计性。

组件:
┌─────────────────────────────────────────────────────────────┐
│                         数据保险库                           │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  中心 (业务键)                                              │
│  ┌────────────────────┐                                     │
│  │ hub_customer       │                                     │
│  │ ├── hub_key     PK │  ← 代理键                          │
│  │ ├── customer_id    │  ← 业务键                          │
│  │ ├── load_date      │  ← 加载时间                        │
│  │ └── source         │  ← 来源                            │
│  └────────────────────┘                                     │
│                                                              │
│  链接 (关系)                                                │
│  ┌────────────────────┐                                     │
│  │ link_customer_order│                                     │
│  │ ├── link_key    PK │                                     │
│  │ ├── hub_customer_fk│                                     │
│  │ ├── hub_order_fk   │                                     │
│  │ ├── load_date      │                                     │
│  │ └── source         │                                     │
│  └────────────────────┘                                     │
│                                                              │
│  卫星 (描述性数据)                                          │
│  ┌────────────────────┐                                     │
│  │ sat_customer_details│                                    │
│  │ ├── hub_customer_fk│                                     │
│  │ ├── load_date   PK │  ← 部分PK                         │
│  │ ├── name           │  ← 描述性属性                      │
│  │ ├── email          │                                     │
│  │ ├── hash_diff      │  ← 变更检测                        │
│  │ └── source         │                                     │
│  └────────────────────┘                                     │
│                                                              │
└─────────────────────────────────────────────────────────────┘

数据保险库优点:
├── 完整审计跟踪 (所有变更跟踪)
├── 来源系统无关
├── 可并行加载
├── 优雅处理模式变更
└── 适合监管要求

数据保险库挑战:
├── 复杂查询 (多连接)
├── 需要呈现层
├── 学习曲线陡峭
├── 比星型模式存储更多
└── 不适合直接BI访问

何时使用数据保险库

数据保险库决策矩阵:

使用数据保险库当:
├── 多个来源系统,不同模式
├── 监管要求审计跟踪
├── 模式变更频繁
├── 历史准确性关键
├── 大型企业,复杂数据环境
└── 从收购集成数据

使用星型模式当:
├── 更简单报告需求
├── 单一来源系统
├── 快速查询性能优先
├── 业务用户直接查询
├── 规模较小,需求更简单
└── 需要快速价值实现

混合方法:
┌─────────────────────────────────────────────────────────────┐
│                                                              │
│  来源系统 ──► 数据保险库 ──► 星型模式 ──► BI工具            │
│  Source      (原始保险库)   (呈现层)     (报告)            │
│  Systems                                                   │
│                                                              │
│  优点:                                                       │
│  ├── 原始保险库: 完整历史,审计                            │
│  ├── 星型模式: 查询性能                                    │
│  └── 解耦: 更改原始而不破坏报告                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

模式演进

模式演进模式

模式演进策略:

1. 添加性变更 (最安全)
   ├── 添加带默认值的新列
   ├── 添加新表
   └── 添加新索引

   安全: 不破坏现有查询

   ALTER TABLE users ADD COLUMN phone VARCHAR(20) DEFAULT NULL;

2. 非破坏性变更
   ├── 扩大列类型 (VARCHAR(50) → VARCHAR(100))
   ├── 移除NOT NULL约束
   └── 添加可选外键

   通常安全,通过测试验证

3. 破坏性变更 (危险)
   ├── 重命名列/表
   ├── 移除列
   ├── 更改列类型
   └── 添加NOT NULL无默认值

   需要迁移策略

迁移模式:
┌─────────────────────────────────────────────────────────────┐
│ 模式: 扩展-收缩                                              │
│                                                              │
│ 阶段 1 (扩展):                                              │
│ ├── 添加新列 (name_new)                                     │
│ ├── 写入新旧列都写
│ └── 回填新列                                                │
│                                                              │
│ 阶段 2 (迁移):                                              │
│ ├── 更新读取器使用新列                                      │
│ └── 验证所有系统已迁移                                      │
│                                                              │
│ 阶段 3 (收缩):                                              │
│ └── 移除旧列                                                │
│                                                              │
│ 时间线: 每阶段几天到几周                                    │
└─────────────────────────────────────────────────────────────┘

版本控制策略

模式版本控制:

1. 单一模式 (最常见)
   ├── 一个模式,原地演进
   ├── 使用迁移 (Flyway, Liquibase)
   └── 所有应用使用相同版本

2. 多版本模式
   ├── 多个模式版本存在
   ├── 应用指定版本
   └── 复杂但允许渐进迁移

   示例: v1_users, v2_users

3. 事件溯源
   ├── 存储事件,而非状态
   ├── 重播到任何模式版本
   └── 最灵活,最复杂

   事件: UserCreated, UserNameChanged, UserDeleted
   → 重播以构建当前状态

迁移工具:
┌────────────────────────────────────────────────────────────┐
│ 工具        │ 语言       │ 方法                            │
├─────────────┼────────────┼─────────────────────────────────┤
│ Flyway      │ Java/SQL   │ SQL迁移,版本化                 │
│ Liquibase   │ Java/XML   │ 变更日志格式,回滚              │
│ Alembic     │ Python     │ SQLAlchemy集成                 │
│ Entity Framework│ .NET   │ 代码优先迁移                    │
│ Prisma      │ TypeScript │ 声明式模式                      │
│ Atlas       │ Go         │ 声明式 + 命令式                 │
└────────────────────────────────────────────────────────────┘

键和标识符

主键策略

主键选项:

1. 自然键
   ├── 业务标识符 (邮箱,SSN,ISBN)
   ├── 优点: 有意义,业务唯一
   ├── 缺点: 可能变更,隐私问题
   └── 使用: 当真正不可变时

2. 代理键 (推荐)
   ├── 自增整数
   ├── 优点: 简单,性能好,稳定
   ├── 缺点: 无意义,数据库特定
   └── 使用: 大多数操作型系统

3. UUIDs
   ├── 全局唯一标识符
   ├── 优点: 全局唯一,分布式生成
   ├── 缺点: 较大,性能较差
   └── 使用: 分布式系统,外部暴露

4. ULIDs / Snowflake IDs
   ├── 时间可排序唯一标识符
   ├── 优点: 可排序,唯一,分布式
   ├── 缺点: 生成更复杂
   └── 使用: 时间序列,事件系统

比较:
┌────────────────────────────────────────────────────────────┐
│ 类型          │ 大小    │ 可排序 │ 分布式 │ 示例      │
├───────────────┼─────────┼──────────┼─────────────┼─────────┤
│ 自增          │ 4-8 字节│ 是     │ 否          │ 12345   │
│ UUID v4       │ 16 字节 │ 否      │ 是         │ a1b2c...│
│ UUID v7       │ 16 字节 │ 是      │ 是         │ 0188... │
│ ULID          │ 16 字节 │ 是      │ 是         │ 01H5... │
│ Snowflake     │ 8 字节  │ 是      │ 是         │ 7890... │
└────────────────────────────────────────────────────────────┘

复合键

复合键:
多列主键。

使用案例:
├── 连接表 (多对多)
├── 时间序列分区
├── 多租户系统
└── 自然业务键

示例: 订单项 (SQL Server - PascalCase)
┌─────────────────────────────────────────────────────────────┐
│ OrderItems                                                   │
│ ├── OrderId     PK, FK                                      │
│ ├── LineNumber  PK       (与OrderId复合)                   │
│ ├── ProductId   FK                                          │
│ ├── Quantity                                                │
│ └── Price                                                   │
└─────────────────────────────────────────────────────────────┘

权衡:
├── 优点: 强制唯一性,自然排序
├── 缺点: 复杂外键,ORM挑战
└── 替代: 代理键 + 唯一约束

最佳实践

数据建模最佳实践:

1. 首先理解用例
   ├── OLTP vs OLAP 需求
   ├── 预期查询模式
   ├── 写vs读比例
   └── 增长预期

2. 从规范化开始,理性反规范化
   ├── 操作型从3NF开始
   ├── 仅为证明的性能需求反规范化
   ├── 记录反规范化决策
   └── 先考虑物化视图

3. 使用一致命名 (数据库特定)
   ├── 单数表名 (User, 非 Users)
   ├── SQL Server: PascalCase (CustomerId, OrderDate, CreatedAt)
   ├── PostgreSQL: snake_case (customer_id, order_date, created_at)
   ├── 外键: {Entity}Id 或 {entity}_id 按约定
   └── 避免保留字

4. 记录一切
   ├── 列描述
   ├── 关系含义
   ├── 业务规则
   └── 变更历史

5. 为变更计划
   ├── 使用代理键
   ├── 设计模式演进
   ├── 版本化模式
   └── 彻底测试迁移

6. 早期考虑性能
   ├── 索引策略
   ├── 分区需求
   ├── 数据类型 (最小足够)
   └── 查询模式

反模式

数据建模反模式:

1. "一表统治所有"
   ❌ 单一表有许多可空列
   ✓ 适当实体分离

2. "实体-属性-值 (EAV)"
   ❌ 通用键-值表
   ✓ 适当列或JSON字段

3. "列中CSV"
   ❌ 逗号分隔值在一个字段
   ✓ 适当连接表

4. "过早反规范化"
   ❌ 未经测量反规范化
   ✓ 从规范化开始,用数据优化

5. "无外键"
   ❌ 跳过外键以 '性能'
   ✓ 使用外键保证完整性,考虑索引

6. "无意义名称"
   ❌ table1, field_a, temp_data
   ✓ 描述性,一致命名

相关技能

  • data-architecture - 数据湖,湖仓一体,数据网格
  • stream-processing - 实时数据建模
  • database-scaling - 缩放数据系统
  • etl-elt-patterns - 数据转换