数据仓库和建模

一、数据库和数据仓库

1、数据库:OLTP(on-line transcation processing),注重:响应实时,可靠性(事务)。遵循3范式。主要有mysql,oracle等
2、数据仓库:OLAP(online analyze procss)。注重:分析和整合分析决策。通常反范式设计,以空间换时间。主要有hive。
数据仓库的目标是实现集成、稳定、反映历史变化有组织有结构的面向主题的存储数据的集合。
汇总所以的数据,为各个部门提供统一的规范的数据出口
特征:

  • 面向主题:汇总所以的数据,针对某个主题
  • 集成性:数据口径一致性(数据字典解释一致,比如男女、M/F)
  • 稳定的:不会删除和更新,只会增加
  • 变化的:历史版本也会保存

二、数仓的分层

大致可以分为4层,企业可根据实际情况调整层次。

  • ODS(Operational Data Store)操作数据存储层。保存的是原始业务数据库/行为数据,数据结构和数据库保持一致,通常遵循第三范式,采用ER建模
  • DWD(Data Warehouse Detail)数据明细层。对ODS层数据进行数据清洗、脱敏、规范化、整合,把脏数据、垃圾数据、规范不一致的、状态定义不一致的、命名不规范的数据处理掉。大多数是维度建模,可分为事实表和维度表,事实表通常会简单的宽化(维度退化)
  • DWS(Data Warehouse service)服务数据层/公共汇总层。对DWD的数据进行轻度汇总,周期粒度包括日、周、历史等。采用维度建模,这边事实表会建更大的宽表减少join的使用。能够满足80%的指标需求。
  • DM(Data market)数据集市层。面向特定的主题(通常通过部门或者业务切分),做汇总报表和指标的统计信息;使用维度建模
    在这里插入图片描述

三、数据仓库技术架构

总体架构:
在这里插入图片描述

3.1.数据采集

数据源主要包括:

  • 业务数据:如订单数据,用户数据。
  • 行为数据:如用户访问记录,停留页面时间等。
  • 其他文件数据:第三方的文件数据等。
3.1.1 业务数据

业务数据通常在RDB中,通过RDB–>同步工具–>数据仓库的方式。
同步工具有:datax,sqoop,kettle。

  • datax:有reader writer的json配置
    优点:支持的数据源广泛,流量控制
    缺点:单节点运作,无页面操作
  • Sqoop:采用Sqoop1的方式
    优点:基于map的分布式同步
    缺点:RDBMS->HDFS、HDFS->RDBMS 类型支持的少,但是够用了
  • kettle
    优点:可视化界面,易操作
    缺点:分布式的吗(待确认)
3.1.1 行为数据

行为数据通常在log中或需要埋点。通过客服端/服务端埋点–>log日志–>采集工具–>数据通道–>数据仓库
采集日志工具有:flume、logstash 都很占资源。
行为埋点:
使用CID和UID做匹配,只有在重新登录、重新注册的时候才会切换cid;通过uid打通不同设备
有app埋点和服务端埋点;属性分为共有属性和私有属性

3.1.1 其他文件数据

通过scp,ftp或者文件上传、kettle同步解析离线同步到数据仓库。

3.2.数据通道

使用kafka,能够起到解耦、消峰的作用。单节点吞吐量很高。且数据不会丢失。

3.3.数据存储

  • hive 高延迟。适合离线。有行数存储和列式存储。列式存储能够有更高的压缩比,针对少量列查询有更好的新能,通常采用parquet列出存储,配合使用Snappy压缩
  • hbase 低延迟 列式存储 通常用于实时计算

3.4.计算引擎

MR < sparkCore < sparksql
我们采用的hive on spark,sparkcore

3.5.系统调度

  • Oozie:重量级,功能全面,基于xml配置,通常封装封装web页面;监控hive等 依赖hive等的版本
  • Azkaban:轻量级

四、数据仓库建模理论

建模的理论:数据仓库建模的目标是通过建模的方法更好的组织、存储数据,以便在性能、成本、效率和数据质量之间找到最佳平衡点。

4.1.数据库3范式

为了减少数据冗余,尽量让每个数据只出现一次,保证数据一致性;获取数据时通过 join 拼接出最后的数据

4.1.1 函数依赖概念
  • 函数依赖:若x确定则y也确定,则称y函数依赖于x
  • 完全函数依赖:若y函数依赖于x,且y不函数依赖于x的真子集,则y完全函数依赖于x
  • 部分函数依赖:若y函数依赖于x,但y不完全函数依赖于x,则y部分函数依赖于x
  • 传递函数依赖:若z函数依赖于y,且y函数依赖于x,则z传递函数依赖于x
4.1.2 3范式
  • 1NF:数据表中的字段不能再切割了,是原子的;若不符合,则把表示多个含义的一个字段拆分成多个字段
  • 2NF:在1NF基础上,字段都完全函数依赖于主键,没有部分函数依赖的关系;若不符合,则把部分函数依赖的关系拆分出来,单独一张表
  • 3NF:在2NF的基础上,字段都完全依赖于主键,不能有传递依赖的关系;若不符合,则把传递依赖关系拆分出来,单独一张表

4.2.ER建模

ER:entity-relation 实体-关系-属性,主要面对OLTP

  • 实体:客观存在的主体 使用矩形表示
  • 属性:对主体的描述、修饰 使用椭圆形表示
  • 关系:实体或实体的物理事件 使用菱形表示

对照关系:实体和实体或者实体和关系之间的对账关系,1对1,m对n。
举例:学生选课;实体:学生,课程;关系:选课
在这里插入图片描述
此建模不适合数据仓库建模,实体太多,需要分析所以的实体和之间的关系,大系统比较复杂,难以分析。

4.3.维度建模

分为维度表和事实表,主要面向分析OLAP 。

4.3.1 事实表

在现实世界中,每一个操作型事件,基本都是发生在实体之间的,伴随着这种操作事件的发生,会产生可度量的值,而这个过程就产生了一个事实表,存储了每一个可度量的事件。
用来存储事实的度量(measure)及指向各个维的外键值;维度表主键度量数据事件描述信息
举例:下单
订单表:(维度表主键)时间外建,用户外建,商品外键,(度量数据)下单数量、价格、(事件描述信息)状态、付款时间

4.3.2 维度表

每个维度表都包含单一的主键列。维度表的主键可以作为与之关联的任何事实表的外键,当然,维度表行的描述环境应与事实表行完全对应。通常为实体
用来保存该维的元数据,即维的描述信息,包括维的层次及成员类别等;
举例:下单
用户表,商品表,时间区域信息

4.3.3 举例

具体实例:
1.背景
某电商平台,经常需要对订单进行分析,以某宝的购物订单为例,以维度建模的方式设计该模型。
2.事实表与维度表的划分
事实表为订单表、子订单表,维度包括商品维度、用户维度、商家维度、区域维度、时间维度。
3.事实表分析
订单中包含的度量:商品件数、总金额、总减免金额; 描述性属性:下单时间、付款时间、订单状态等;
子订单包含度量:商品ID、单价、减免金额;描述性属性:加入购物车时间、下单时间、付款时间、状态;
4.维度表分析
商品维度:商品 ID、商品名称、商品品类、单价、颜色、尺寸、生产商等;
用户维度:用户 ID、姓名、性别、生日、职业、信用值、收货地址等;
时间维度:日期 ID、日期、周几、是否周末、是否假期等;
区域维度:区域 ID,县/区、县/区 ID、市、市 ID、省、省 ID;
我们往往会避免事实表之间产生关系;子订单中会冗余主订单的用户id,区域id,时间id
在这里插入图片描述

4.3.4 星型模型和雪花模型

  • 星型模型:一个事实表关联多个维度表,一个维度表扁平的设计,反范式 减少join,减少MR
  • 雪花模型:一个事实表关联多个维度表,维度表也会关联其他维度表,符合3范式设计
  • 星座模型:多个事实表共用了维度表,组成了大的星座模型

模型的选择:尽量选择星型模型,用空间换时间,通常我们的系统里面都是星座模型
建模的方式:
1、完全按照维度标准建模
2、将常用字段做事实表,不常用作为维度表
3、维度退化(降维):上面2个相结合,将维度表中经常使用的字段放到事实表中

五、维度建模方法

5.1.同步数据策略

全量同步
适合数据量小的,如果关注状态变更(行的属性值有变动,如果订单状态),一天一个分区;
增量同步
针对表数据量比较大的,以ID/CreateTime或者updateTime为标记同步

  • 无状态:每天同步增量数据,已ID/CreateTime作为每天同步的切割标志。
  • 有状态:需要关注状态变化的。抽取昨天有更新的表记录,和前天的全量数据,做拉链表,通过starttime和endTime做分割

5.1.维度表设计

1、代理键:代理键是由数据仓库处理过程中产生的、与业务本身无关的、唯一标识维度表中一条记录并充当维度表主键的列,也是描述维度表与事实表关系的纽带。可以是业务主键,也可以是专门的代理键;在合并多种维度出现相同业务id或拉链表时使用
2、稳定维度:属性不会变化的维表;时间维度、区域维度;全量同步/增量
3、缓慢渐变维:维度属性会随着时间发生变化,变化速度比较缓慢,这种维度数据通常称作缓慢渐变维;比如用户维度:修改用户收件地址、用户昵称等

  • 每天全量快照:适合数据量小的
  • 增加历史值的字段,一般不使用
  • 采用拉链表:一个原始记录再拉链表中有多条记录,通过startTIme和endtime来区分,这样原始业务id会重复,需要增加额外的代理主键;事实表中存代理键,在事实表新增数据时,需要通过原来的主键,通过time取到代理主键

5.2.事实表设计

增量同步

  • 无状态:增量
  • 有状态且需要记录:拉链表

全量快照

5.2.1 明细事实表

来自dwd层,优化说明
1、数据降维:将维度表中的常用字段放到事实表中
2、独立维度的选择:维度之间可以合并,把不是重点关注的维度合并到其他维度:滴滴下单。用户信息、司机信息、汽车信息。汽车维度可以合并到司机信息里面
3、事实表中不一定有度量信息,比如信息审核表,没有度量信息

设计方案
1、单事件事实表:每个事件一个表
2、流程事件表:一个流程一个表,可能包括多个事件
举例:滴滴打车:单事件:下单 接单 跑单 支付 评价
单事件:
优点:接近于无状态事实表,流程清晰,更方便跟踪业务流程细节数据,针对特殊的业务分析场景比较方便和灵活,数据处理上也更加灵活;
缺点:想要分析整个行为不够直观,join太多
流程事实表:
优点:很直观看到结果,适合大多数应用场景,比较少的join
缺点: 缺失细节,特殊场景的分析不够灵活
可结合2中设计,一般都有。

5.2.2 聚合事实表

来自dws,做初步聚合,以下聚合方式

  • 日粒度:一天中的统计信息:一天的下单数
  • 周期性累积(周,月,年):周期统计
  • 历史累积(累计订单量、累计金额):用户表:累计支付多少 累计下单
  • 公共聚合:需满足80%的指标;比如订单维度所有订单统计信息;用户维度:用户的下单笔数 评价笔数

聚合的数据分为可累加事实和不可累加事实
可累加:订单数 金额
不可累加:率;拆分存储,分为分子和分母

六、规范设计

6.1 表命名规范

层次_数据域_修饰/描述_范围/周期

数仓层次数据域数据域周期/数据范围
共用维度dim订单ord日快照d
集市dm用户user增量i
ODSo财务fincw
DWDs账单bill拉链表l
DWSs库存sto非分区全量表a
<think>好的,用户现在问的是大数据维度建模中的维度退化是什么。首先,我需要确认用户对维度建模的基础知识是否了解。维度退化维度建模中的一个概念,可能用户在学习或工作中遇到了这个术语,或者在设计数据仓库时需要应用它。 接下来,我需要回忆维度建模的基本结构。维度建模通常包括事实表维度表,事实表存储业务过程的度量,而维度表存储描述性属性。维度退化指的是将某些维度属性直接存储在事实表中,而不是作为单独的维度表存在。 为什么会发生维度退化?可能是因为某些维度属性非常简单,比如只有一两个字段,单独创建维度表反而会增加连接的复杂性,低查询效率。例如,订单号可能直接放在事实表中,而不需要单独的订单维度表。 用户可能想知道维度退化的优缺点。优点包括减少表连接,提升查询性能,简化模型结构。缺点可能有数据冗余,护困难,比如如果退化维度属性需要更新,可能需要更新大量事实表记录。 还要考虑用户的应用场景。如果是大数据环境,比如使用Hadoop或Spark,维度退化可能对分布式系统的性能有不同的影响。需要解释在大数据环境下如何处理这种情况,比如通过冗余存储来避免跨节点的连接操作。 可能用户的实际问题是在设计数据仓库时,是否应该将某些维度退化,或者如何判断哪些维度适合退化。这时候需要给出一些判断标准,比如属性的复杂度、更新频率、是否与其他维度关联等。 另外,用户可能对维度退化与缓慢变化的处理有疑问。需要说明退化维度如何处理变化,比如如果订单号不会改变,那么直接存储在事实表中没问题,但如果某个属性会变化,可能需要其他策略。 还要注意术语的准确性,确保维度退化(Degenerate Dimension)与其他概念如退化维度表(Degenerate Dimension Table)区分开,避免混淆。 最后,需要给出实际例子,比如订单号作为退化维度,帮助用户更好地理解。同时,结合大数据环境的特点,说明维度退化在分布式系统中的优势注意事项,比如存储优化查询效率的平衡。 总结来说,回答需要涵盖维度退化的定义、原因、优缺点、应用场景、判断标准以及实际案例,特别是结合大数据环境的考虑,确保用户能够全面理解并在实际项目中应用这一概念。</think>以下是关于大数据维度建模维度退化的详细解析: --- ### 一、核心定义 **维度退化(Degenerate Dimension)** 是维度建模中的特殊设计模式,指**将某些本应作为独立维度存在的属性,直接存储到事实表中**,形成仅包含键值(无独立维度表)的"退化维度"。这类维度在物理存储上表现为事实表的普通字段,但在逻辑上仍保持维度属性特征。 --- ### 二、典型场景与示例 #### 1. **交易流水场景** | 字段名称 | 类型 | 说明 | |----------------|--------------|--------------------------| | transaction_id | 退化维度 | 交易流水号(唯一标识) | | order_id | 退化维度 | 关联订单号 | | product_sk | 标准维度键 | 商品维度代理键 | | amount | 事实度量 | 交易金额 | **为什么需要退化**: 订单号/流水号通常满足以下特征: - 唯一标识且无其他描述属性 - 不与其他维度表关联(如无订单维度表) - 高频直接查询条件 #### 2. **日志分析场景** 在用户行为日志事实表中: ```sql CREATE TABLE user_click_fact ( click_id STRING, -- 退化维度(点击事件唯一ID) user_sk BIGINT, -- 用户维度代理键 page_sk INT, -- 页面维度代理键 click_time TIMESTAMP, -- 时间戳(可关联时间维度) device_type STRING -- 直接存储设备类型(退化维度) ); ``` --- ### 三、技术实现特点 #### 1. **存储结构对比** | | 标准维度表 | 退化维度 | |----------------|------------------------------|------------------------| | 存储形式 | 独立表(含代理键+属性) | 事实表内普通字段 | | 数据量 | 相对较小(维度基数有限) | 与事实记录数相同 | | 更新机制 | 需要处理缓慢变化(SCD) | 直接覆盖或追加 | | 典型使用场景 | 商品、客户等复杂维度 | 交易号、票据号等简单标识 | #### 2. **Hive中的处理优化** 在大数据平台中常用以下策略: ```sql -- 标准维度关联(需要JOIN操作) SELECT f.sales_amount, d.product_name FROM sales_fact f JOIN product_dim d ON f.product_sk = d.product_sk; -- 退化维度直接使用(无需JOIN) SELECT transaction_id, amount FROM sales_fact WHERE transaction_id = 'TX202308150017'; ``` --- ### 四、设计决策指南 #### 判断是否采用维度退化的标准: 1. **属性复杂度** - ✅ 适合退化:单值无层次结构(如订单号、序列号) - ❌ 不适合:含多层级属性(如地理位置:国家-省-市) 2. **查询模式** - ✅ 高频作为过滤条件(如`WHERE order_id = 'X'`) - ❌ 需要基于该维度进行聚合分析(如按产品类别统计) 3. **数据更新需求** - ✅ 属性永不更新(如历史交易号) - ❌ 需要跟踪历史变化(如订单状态变更) 4. **存储成本考量** - ✅ 字段长度短(如数字型ID) - ❌ 长文本字段(如客户备注信息) --- ### 五、大数据环境下的特殊考量 #### 1. **分布式系统影响** 在Hadoop/Spark体系中: - **优势**:避免跨节点Shuffle(减少维度表JOIN带来的网络开销) - **风险**:数据膨胀(例如存储10亿条事实记录时,冗余存储长字符串ID) #### 2. **列式存储优化** 使用Parquet/ORC格式时: ```shell # 在Hive中创建表指定压缩格式 CREATE TABLE sales_fact ( transaction_id STRING COMMENT '退化维度', product_sk BIGINT, amount DECIMAL(10,2) ) STORED AS ORC tblproperties ("orc.compress"="SNAPPY"); ``` - 退化维度字段因高基数不适合做字典编码 - 优先将退化维度放在文件末尾(列存储中最后读取) #### 3. **与维度桥接表对比** 当处理多值维度时: | 方案 | 存储结构 | 适用场景 | |-----------------|------------------------------|------------------------| | 维度退化 | 直接存储在事实表 | 简单单值场景 | | 桥接表 | 单独建立多值关联表 | 医生-患者多次就诊关系 | | 列展开 | 将多个值拆分为多列 | 固定数量多值(如手机多号) | --- ### 六、实际应用案例 #### 淘宝订单系统设计 在淘宝交易事实表中包含的退化维度: ```sql CREATE TABLE taobao_trans_fact ( order_id BIGINT, -- 退化维度(日均2亿+记录) buyer_id STRING, -- 用户维度代理键 item_sk INT, -- 商品维度代理键 payment_time TIMESTAMP, coupon_ids ARRAY<STRING> -- 优惠券ID集合(多值维度特殊处理) ) PARTITIONED BY (dt STRING); ``` **处理逻辑**: 1. 对`order_id`建立全局二级索引(HBase协处理器实现) 2. 将`coupon_ids`通过比特位图编码压缩存储 3. 使用`buyer_id`+`item_sk`组合Bloom Filter加速查询 --- ### 七、反模式警示 以下情况需谨慎使用维度退化: 1. **违反业务语义** - 错误案例:将客户等级(VIP1/VIP2)作为退化维度,而该属性需要关联会员权益规则 2. **导致事实表过度膨胀** - 错误案例:在点击流事实表中存储500字节的URL完整路径 3. **影响数据一致性** - 错误案例:多个事实表重复存储同一订单的状态描述("已付款"/"已发货") --- ### 八、演进趋势 随着大数据技术的发展: 1. **动态退化**:在Alluxio内存加速层保留维度数据,根据查询热度决定是否物化到事实表 2. **智能决策**:基于代价优化器自动选择退化策略(如Spark Adaptive Query Execution) 3. **新型存储融合**:利用Hudi的增量更新特性,实现退化维度的准实时同步 --- ### 总结 维度退化是平衡查询性能与模型规范性的重要技术手段,其本质是**用存储冗余换取计算效率**。在大数据场景下,需重点考虑: 1. 分布式存储带来的数据膨胀影响 2. 列式存储格式的编码效率 3. 查询引擎的优化器特性 正确的退化维度设计可使查询性能提升3-10倍(根据阿里云MaxCompute实测数据),但需要严格遵循**"无属性、无变更、高筛选"** 三原则。建议在设计初期通过数据探查工具(如Apache Atlas)分析字段特征,再结合业务需求做出决策。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值