数仓建模:范式建模

三范式 & E-R 模型

1. 范式建模的概念

1.1. 三范式 & 四范式 & 五范式:

  • 第一范式:
    • 保证数据的原子性,没有重复列,列不可再分,也没有重复行;
    • 数据规整成二维表;
    • 确保每一列表达同一含义;
      • 比如成绩中,分数和评价,要拆分成两列;
    • 去掉多值属性;
      • 比如:地址信息,拆分成省、市、区、详细地址;
    • 拆成多列;
      • 比如:一个人有多个电话号码,应拆分成电话_1、电话_2;
    • 去掉重复组,挪到新表里面;
      • 不好拆分的列,可以单独建表;
      • 比如:每个人都有多个电话,就可以单独建一个电话号码表,新表中每一行、写入一组人员ID+电话号码;
    • 确定主键;
      • 确保每一行都是唯一的;
  • 第二范式:
    • 确保表中的每列都和主键相关;
    • 也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中;
    • 如果不遵守第二范式:
      • 会比存在数据冗余;
      • 同时存在数据不一致的风险;
      • 另外,关系也会被隐藏在表中,不能很直观的展示出来;
    • 比如:下方学生成绩表中,学生姓名、学生课程,各自都只与主键学号有关,这是就应该拆分成两个表;
  • 第三范式

    • 非主键属性只能依赖于主键,不能依赖于其他非主键属性;
    • 如果非主键属性、依赖于其他非主键属性,则需要移出去创建新表;
    • 比如:下方学生班级成绩表中,班级名称依赖于班级编号,而不是主键学号,这是就应该分拆成两个表;
  • BCNF

    • BCNF 中,任何属性(包括主属性和非主属性),都不能被非主属性所决定;
    • BCNF 必须规避下面的问题:
      • 存在联合主键;
      • 存在多个可选键;
        • 可选键存在重叠;
      • 比如:下表中,班级+课程、班级+教师,都可以作为联合主键,就可以拆分成两个表;
  • 第四范式

    • 多值依赖;
      • 多值依赖:三个属性A、B、C在一起做联合主键,AB、AC都存在依赖关系,并且B和C之间没有依赖关系;
      • 第四范式就是要消除多值依赖;
    • 比如:下表中,学号、课程、语言做联合主键,学号+课程、学号+语言,是相互依赖的,但是课程和语言没有依赖关系,这时候就要拆分成两个表;
    • 第四范式下:
      • 数据冗余会减少;
      • 数据关系会更清晰;
  • 第五范式

    • 连接依赖:
      • 连接依赖:三个属性A、B、C在一起做联合主键,AB、AC、BC都存在依赖关系;
      • 第五范式就是要消除连接依赖;

  • 范式模型常见表类型:
    • 主数据表;
    • 参照数据表;
    • Xref 表;
    • 事务表;
  • 三范式的优点:
    • 减少冗余,同一含义的数据只存一份;

1.2. E-R 模型

  • E-R 模型的组成是由实体,属性和联系。

  • 实体 Entity
    • 实体,是具体事物的抽象化描述,是数据库中存储的所有信息;
    • 实体,对应数据库的表;
    • 实体中的实例,指的就是一行行的数据;
    • 每个实体(除非是弱实体)都必须有一个唯一标识属性的最小化集合。这个集合叫做实体的主键。

    实体,通常指的是业务场景中【名词】,也指一个要处理的抽象的【对象】。

  • 关系 Relationship

    • 一对一
      • 指实体之间的关系是一一对应的,比如个人与身份证信息之间的关系就是一对一的关系。
    • 一对多
      • 指一边的实体通过关系,可以对应多个另外一边的实体。相反,另外一边的实体通过这个关系,则只能对应唯一的一边的实体。
      • 比如说,我们新建一个班级表,而每个班级都有多个学生,每个学生则对应一个班级,班级对学生就是一对多的关系。
    • 多对一
      • 与一对多情况相反。
    • 多对多
      • 指关系两边的实体都可以通过关系对应多个对方的实体。比如在进货模块中,供货商与超市之 间的关系就是多对多的关系,一个供货商可以给多个超市供货,一个超市也可以从多个供货商那里采购商品。
  • ER图示例

2. 实体 Entity

2.1. 实体的定义

  • 实体是一个数据的使用者,其代表软件系统中客观存在的生活中的实物,如人、动物,物体、列表、部门、项目等,而同一类实体就构成了一个实体集。
  • 实体中的所有特性称为属性,如用户有姓名、性别、住址、电话等。
  • “实体标识符”是在一个实体中,能够唯一表示实体的属性和属性集的标示符,但针对于一个实体只能使用一个”实体标识符”来标明。实体标识符也就是实体的主键。
  • 实体不会是单独存在的,实体和其他的实体之间是有着千丝万缕的联系的。

2.2. 实体的分类

3. 属性 Attribute

3.1. 属性的定义

  • 属性,对应的是表的列;
  • 在关系型数据库中,属性通常都是单值的;
    • 如果存在多值,则需要另外建属性表;

3.2. 属性的分类

  • ID;
    • 标识实体的唯一性,一般是唯一主键;
  • 描述;
  • 引用;
    • 引用的其他实体的信息,比如订单表中会引入商品信息、客户信息,就需要加入商品ID、客户ID;
  • 分类;
    • 实体所属的分类,比如客户分为国内客户、国外客户;
    • 注意:不同分类方法,会对应不同的属性值,需要注意对应关系和唯一性;
  • 限制;
    • 比如:最低价格;
  • 数量;
    • 比如:订单的采购数量、交易的金额等;
  • 时间相关;
    • 日期型;
    • 时间戳性;
    • 时间型;
  • 人物相关;
    • 比如:企业法人;
  • 组织相关;
    • 比如:销售门店;
  • 地点相关;
    • 比如:城市、国家、IP地址;
  • 途径相关;
    • 比如:销售途径平台电商、自建独立站、直播间、代理商;
  • 站点相关;
    • 比如:APP、web 站;
  • 状态;
    • 比如:员工在职、离职;
  • 审计;
    • 数仓中最常用的;
    • 创建、修改间戳;
      • 比如:add_time、update_time;
    • 操作人;
      • 订单录入人、系统自动生成等;
    • 数据来源;
      • 数据的来源;
      • 比如:客户姓名、来自于客户信息系统,就要标注客户信息系统ID;
  • 派生;
    • 预计算数据;
    • 数据内容的 MD5 校验码;
      • ETL 数据对账中经常使用;

3.3. 属性的特性

  • 强制 / 可选
    • 属性值是否可以为空;
  • 原子 / 组合
    • 比如:姓、名都是原子的,二者在一起,组合构成姓名;
  • 直接 / 派生
    • 比如:国家 + 省 + 城市 + 街道 + 门牌号 = 详细地址;
  • 单值 / 多值
    • 关系型数据,不支持单实体、多属性,否则会违反 3NF,需要单独建子表;
  • 可选键
    • 某一属性、或多个属性,可以作为判断唯一性的标识,即唯一键;
  • 数据类型
    • INT、CHAR、DATE 等等;
  • 默认值
    • 如果没有值,则赋与其默认值;
    • 比如:审计中的更新时间,为系统自动生成时间 current timestamp;
  • 派生属性计算逻辑
    • 比如:手机号前缀(如+86) + 手机号 = 完整手机号;

4. 值域 Domain

4.1. 值域的定义

  • 值域,指的是属性所有取值范围的集合;
  • 值域,可以理解为自定义的数据类型,同时可以加上约束条件;
  • 值域范围,需要根据实际的业务场景决定取值范围;

4.2. 值域的类型

  • 格式:
    • varchar;
    • currency;
    • email;
      • 正则表达式匹配 @ 符:
    • 身份证号;
      • 位数限制、校验码;
    • 等等;
  • 列表:
    • 枚举;
      • 比如:销售渠道包含淘宝店、京东店铺、抖音店铺,除此以外的值都是非法;
    • 月份;
      • 从 1月 到 12 月;
    • 性别;
      • Male、Female、Unknown;
    • 名称:
      • LongName:VARCHAR(255),容纳公司名称、其他名称;
      • ShortName:VARCHAR(50),容纳人名、部门名称;
    • 等等;
  • 范围:
    • 年龄:0 ~ 100;
    • 角度:-180 ~ +180;

4.3. 值域的作用

  • 数据质量:
    • 值域范围规范,可以大幅提高数据质量;
  • 易懂易用:
    • 数据模型会更加容易理解和使用;
  • 数据标准化:
    • 提高模型质量和建模效率;

4.4. 值域的应用

  • PostgreSQL、Oracle;

注意:MySQL,不支持值域!!!

5. 关系

5.1. 一对一

指实体之间的关系是一一对应的,比如个人与身份证信息之间的关系就是一对一的关系。

5.2. 一对多

指一边的实体通过关系,可以对应多个另外一边的实体。相反,另外一边的实体通过这个关 系,则只能对应唯一的一边的实体。比如说,我们新建一个班级表,而每个班级都有多个学生,每个学生则对应一个班级,班级对学生就是一对多的关系。

5.3. 多对一

与一对多情况相反。

5.4. 多对多

指关系两边的实体都可以通过关系对应多个对方的实体。比如在进货模块中,供货商与超市之 间的关系就是多对多的关系,一个供货商可以给多个超市供货,一个超市也可以从多个供货商那里采购 商品。

5.5. E-R 关系图

6. 键 Key

6.1. 候选键

  • 一个或多个属性的结合,可以确定唯一实体;
  • 比如:
    • 员工编号、员工邮箱,都是唯一的,可以作为候选键;

6.2. 主键

  • 从候选键中,选中作为唯一标识的属性、或者属性组;

  • 主键的特点:
    • 唯一性:不可重复;
    • 强制性:不可以为空;
    • 永久性:不可以改变;
    • 最小集合:不可以掺杂多余的属性;

      如果两个字段可以作为联合主键确定唯一值,就没有必要再加上第三个字段;

  • 设计主键要注意的问题:
    • 尽量不要使用 SmartKey;
      • SmartKey,指的是存在含义的编码 Key;
      • 比如:身份证号码,对应位置的数值,是有特殊含义的,比如行政区域,这就存在超级辖区人口数量暴增,导致数值溢出的风险;
    • 不要将 ID 编码植入程序,
      • 否则一旦编码变化、程序会出现很大问题。
      • 比如:部门编码,指定位置指定对应的部门,但是如果组织架构调整,就会出现问题;
    • 不能随着环境变化而收到影响
      • 设计之初,就要考虑未来可能遇到的场景;
    • 键值应易管理、易维护;
      • 不要有人工输入;

6.3. 单键 & 复合键

  • 单键:
    • 主键只有一个属性,称为单键;
  • 复合键:
    • 主键是多个属性的组合,称为复合键;

6.4. 自然键 & 代理键

  • 自然键:
    • 已经真实存在的键,通常具有真实的商业含义;
    • 可以使单键,也可以是复合键;
    • 灵活性:
      • 自然键做主键,实体主键的变化、会带来外键相关表的连锁反应;
      • 一旦 update,只能删除重做;
  • 代理键:
    • 完全没有商业含义,通常由系统自动生成;
    • 灵活性:
      • 代理键本身无意义,可以修改原自然键内容;
      • 代理键 update 会更加容易;
    • 使用场景:
      • 完全没有自然键做主键;
      • 分布式结构数据库,多联合主键的事实表,为了分区方便,创建单独的代理键,以避免数据分区的偏移;
  • 外键:
    • 引用其他表的主键;

6.3. 可选键

  • 候选键中,没有选中的其他键;

6.4. 键的命名规则

  • 自然键
  • 代理键
    • xxx_SK
  • Checksum key
    • xxx_CK

7. 约束

7.1. 唯一标识

  • unique key;

7.2. 非空约束

  • not null;

7.3. 默认值

  • default;

7.4. 检查

  • 属性取值符合规则;

7.5. 实体完整性(Entity integrity)

  • 主属性不能为空值(即任一候选码的属性不能为空);
  • 在实际上,只要主键属性不为空就好;

7.6. 参照完整性(Referential integrity)

  • 这是对外键的约束:
  • 外键只能有两种取值情况:
    • 这个外键在对应的表中是存在的;
    • 空值;

8. 建模经验

8.1. ID 设计

  • 8位 / 10位 / 15位 流水号;
    • 如果从 1、2、3 开始,ID 长度都会不一致,
  • 设计规则
    • 前 2位(3位) 对应业务系统,后面为流水号;
    • 注意流水号要考虑到数据增长情况;
    • 项目整体规范化、标准化;

8.2. 表名称统一命名

  • 统一的命名规则
    • ods_业务系统简称_业务系统原始表名称
    • dwd_业务系统简称_业务系统原始表名称

8.3. 有限可穷举字段,一般用代码表示

  • 主要是为了统一标准格式;
  • 比如:国家、民族,长度不一致,
    • 可以通过关联对应的字典表获取,
    • 国家有统一发布的规范标准。

8.4. 第一范式必须严格遵守

  • 遵守第一范式,是范式建模的基础

8.5. 数据与数据的关系,用表关联的方式体现出来

  • 数据与数据的关系,用表关联的方式体现出来,而不是用数据内容来体现

8.6. 尽可能的减少冗余

  • 同一含义的数据,尽可能只存一分

8.7. 一般不用第四范式和第五范式

  • 第四范式和第五范式,可以参考但实际不常用;

9. 建模工具

  • Powerdesigner
  • E-Rwin;
  • Datablau;