大厂数据仓库数据建模八股文面试题及参考答案(虾皮希音Bigo等多家公司汇总)
什么是数据仓库,和数据库有什么区别?
数据仓库(Data Warehouse,DW)是专门为支持企业决策而设计的系统,通过整合来自不同来源的数据,提供统一的分析视图。其核心目标是支持复杂的查询、历史数据分析和数据挖掘。数据仓库通常采用非规范化结构(如星型模型或雪花模型),并围绕业务主题(如销售、库存)组织数据。
数据库(Database)则主要用于事务处理(OLTP),支持日常业务操作,如订单录入、用户注册等。数据库设计遵循规范化原则(如第三范式),以消除冗余并确保事务的原子性和一致性。
区别对比
设计目标 | 支持决策分析(OLAP),处理复杂查询和聚合操作 | 支持事务处理(OLTP),保证数据增删改查的高效性和一致性 |
数据结构 | 非规范化设计(星型/雪花模型),冗余数据多,便于快速分析 | 规范化设计(如第三范式),冗余少,结构复杂 |
数据时效性 | 存储历史数据(可能包含多年数据),定期批量更新(ETL) | 存储当前数据,实时或近实时更新 |
查询类型 | 复杂分析查询(多表关联、聚合、窗口函数等),数据量大 | 简单事务查询(单行操作、索引扫描),数据量相对较小 |
用户群体 | 数据分析师、决策层 | 应用系统、业务人员 |
示例场景
- 数据库:电商平台的订单表实时记录用户下单信息,每次下单会插入一条新记录,并通过索引快速检索订单状态。
- 数据仓库:将订单表与用户表、商品表整合,分析“2023年某品类商品的季度销售额趋势”,需关联多表并计算聚合值。
数据仓库的基本原理是什么?
数据仓库的核心原理围绕数据整合、分析优化和历史数据管理展开,具体包括以下要点:
- 集成性数据仓库从多个异构数据源(如数据库、日志文件、API)抽取数据,通过清洗、转换(ETL/ELT)消除数据差异(如字段名冲突、单位不统一),最终存储为统一格式。例如,将不同系统的“金额”字段统一为人民币单位。
- 主题导向数据按业务主题(如客户、产品)而非应用功能划分。每个主题域包含相关的事实表(如销售事实)和维度表(如时间维度),便于从业务角度分析数据。
- 非易失性数据仓库的数据通常只追加不修改(Insert-Only),即使源系统数据被删除或更新,仓库中仍保留历史快照。例如,用户地址变更后,仓库可能保留变更前后的记录以支持历史分析。
- 时变性数据仓库记录数据随时间变化的状态。例如,使用“缓慢变化维度”(SCD)技术跟踪客户会员等级的变化历史。
技术实现原理
- ETL流程:Extract:从源系统抽取数据(全量或增量)。Transform:清洗(去重、补全)、转换(计算衍生字段)、聚合(预汇总)。Load:加载到目标表,可能采用分区或列式存储优化查询性能。
- 存储结构:采用列式存储(如Parquet)减少I/O,或使用MPP架构(如Hive on Spark)并行处理查询。
数据仓库架构是怎样的?
数据仓库的架构通常分为三层,但具体实现可能因企业需求和技术选型有所差异:
- 数据源层包括内部系统(如MySQL、ERP)和外部数据(如第三方API、日志文件)。数据可能以结构化(表)、半结构化(JSON)或非结构化(图片)形式存在。
- ETL层负责数据加工:
- 抽取:通过工具(如Sqoop、Flink CDC)捕获增量数据。
- 清洗:处理脏数据(如NULL值、格式错误)。
- 转换:关联维度、计算指标(如用户留存率)。
- 加载:写入目标存储(HDFS、Hive表)。
- 存储层
- ODS(操作数据存储):近原始数据,供临时查询或重新加工。
- DWD(明细层):清洗后的明细数据,按主题组织。
- DWS(汇总层):预聚合的指标(如每日销售额)。
- ADS(应用层):面向业务的数据集市(如报表、API接口)。
- 服务层 提供数据查询(OLAP引擎如Presto)、可视化(如Tableau)和API服务(如Restful接口)。
现代架构扩展
- Lambda架构:结合批处理(高延迟高准确)和流处理(低延迟近似)。
- 数据湖架构:存储原始数据(包括非结构化),按需转换为数仓结构。
数据仓库分层(层级划分),每层做什么?分层的好处是什么?数据分层是根据什么?数仓分层的原则与思路是什么?
分层结构
- ODS(操作数据层)存储从源系统抽取的原始数据,仅做简单清洗(如去重、字段格式化)。保留历史快照,供数据回溯使用。
- DWD(明细数据层)对ODS层数据进行深度清洗(如处理NULL值、统一单位),并按业务主题建模(如订单事实表、用户维度表)。此层数据粒度最细,通常采用星型模型。
- DWS(汇总数据层)基于DWD层预计算常用指标(如用户月活、商品销量Top10),减少重复计算。例如,创建“每日销售汇总表”以加速报表生成。
- ADS(应用数据层)直接面向业务需求,如生成报表(BI工具直接读取)、推荐系统特征表等。此层可能包含高度聚合的数据或特定业务逻辑加工的结果。
分层的好处
- 解耦:各层职责明确,修改某一层不影响其他层(如ODS结构调整只需适配DWD)。
- 复用性:DWS层的预聚合指标可被多个业务复用,避免重复计算。
- 数据一致性:通过分层加工确保指标口径统一(如“销售额”在DWD层明确定义)。
分层依据
- 数据处理阶段:从原始数据到应用数据的逐步加工过程。
- 数据粒度:从细粒度(DWD)到粗粒度(DWS)的过渡。
- 业务需求:根据最终应用场景(如实时报表、机器学习)设计ADS层。
分层原则
- 高内聚低耦合:每层专注于单一职责(如DWD仅处理明细数据)。
- 可追溯性:支持数据血缘追踪(如ADS层指标可追溯至DWD字段)。
- 性能优化:通过分层预计算减少查询响应时间。
数仓建模常用模型有哪些?区别、优缺点是什么?星型模型和雪花模型的区别?应用场景?优劣对比如何?
常用模型
- 范式模型(Inmon流派)特点:遵循数据库规范化设计(第三范式),减少冗余。优点:数据一致性高,适合频繁更新的场景。缺点:查询需多表关联,性能较差。场景:适用于ODS层或需要高度一致性的操作型系统。
- 维度模型(Kimball流派)星型模型:事实表直接关联多个维度表,维度表非规范化。 优点:查询简单(关联少),性能高。缺点:维度冗余(如国家-省份-城市合并为“地区”维度)。雪花模型:维度表进一步规范化(如地区维度拆分为国家、省份表)。 优点:减少冗余,节省存储。缺点:查询复杂度高(需多层关联)。
星型 vs 雪花模型对比
结构 | 事实表 + 非规范化维度表 | 事实表 + 规范化维度表(可能多层) |
查询性能 | 高(关联少) | 低(多层关联) |
存储开销 | 高(维度冗余) | 低(维度无冗余) |
适用场景 | 高频分析(如报表、即席查询) | 需要节省存储或维度频繁更新的场景 |
示例
- 星型模型:销售事实表直接关联“产品维度表”(包含产品名称、类别、品牌)。
- 雪花模型:将“产品维度表”拆分为“产品表”和“类别表”,通过外键关联。
建模选择
- 优先星型模型以提高查询性能,仅在维度数据量极大(如百万级)时考虑雪花模型。
数仓建模有哪些方式?数仓建模的流程是什么?
数据仓库建模的核心方式包括范式建模、维度建模和Data Vault建模,每种方式适用于不同场景:
- 范式建模(Inmon方法)遵循数据库规范化原则(如第三范式),强调数据一致性和低冗余。数据按主题域划分,通过实体关系(ER)模型设计,通常用于企业级数仓的全局设计。优点:数据冗余少,更新效率高。缺点:查询复杂,需要多表关联,分析性能较低。
- 维度建模(Kimball方法)以业务过程为中心,采用星型模型或雪花模型设计,包含事实表和维度表。优点:查询性能高,适合分析场景。缺点:数据冗余较多,存储成本较高。
- Data Vault建模由中心表(Hub)、链接表(Link)和卫星表(Satellite)组成,适用于需要高扩展性和审计能力的场景(如数据湖)。优点:支持历史追溯和灵活扩展。缺点:实现复杂,查询需多层关联。
建模流程
- 需求分析与业务方沟通明确分析目标(如销售额分析、用户行为分析),确定核心业务过程(如“下单”“支付”)。
- 概念模型设计定义主题域(如“销售主题”包含订单、商品等实体),确定数据范围和关键指标。
- 逻辑模型设计选择建模方式(如维度建模),设计事实表与维度表的结构。例如:事实表:订单事实表(订单ID、金额、时间)。维度表:时间维度表(日期、周、季度)。
- 物理模型设计根据技术选型(如Hive、ClickHouse)定义存储格式(Parquet)、分区策略(按天分区)和索引。
- ETL开发编写数据清洗和转换逻辑。例如,使用SQL处理数据倾斜:
- 验证与优化通过数据血缘工具追踪指标来源,优化查询性能(如预聚合、物化视图)。
维度建模的步骤有哪些,如何确定这些维度?维度建模和范式建模区别是什么?
维度建模步骤
- 选择业务过程明确分析目标对应的业务事件(如“用户下单”),确定事实表的核心行为。
- 声明粒度定义事实表的记录粒度(如“单个订单项”或“每日汇总”),需确保粒度不可再分。
- 确定维度围绕业务过程提取描述性属性:直接维度:如订单表中的“用户ID”“商品ID”。衍生维度:通过ETL生成(如“用户年龄层”基于出生日期计算)。
- 确定事实定义可度量的数值字段(如“订单金额”“商品数量”),区分类型:可加事实:可跨维度求和(如销售额)。半可加事实:仅部分维度可加(如库存量按时间不可加)。
- 模型设计构建星型模型(推荐)或雪花模型,例如:
维度确定方法
- 业务文档分析:参考需求文档中的筛选条件(如“按地区分析销量”对应“地区维度”)。
- 数据探查:通过SQL查询源表字段分布,识别高频筛选字段。
维度建模 vs 范式建模
设计目标 | 优化查询性能,支持分析场景 | 减少冗余,确保数据一致性 |
结构 | 星型/雪花模型,事实表关联维度表 | 高度规范化,多表关联 |
适用场景 | 数据仓库、数据集市 | 操作型数据库、ODS层 |
维度表和事实表的区别是什么?什么是 ER 模型?
维度表与事实表对比
内容 | 描述性属性(如用户姓名、商品分类) | 可度量的数值(如订单金额、点击次数) |
数据量 | 相对较小(通常千到百万级) | 极大(可能亿级或更大) |
更新频率 | 低频更新(如用户地址变更) | 高频插入(如每笔订单插入一条记录) |
示例
- 维度表:
dim_user
包含 user_id、gender、age_range。 - 事实表:
fact_sales
包含 sale_id、user_id、sale_amount。
ER模型(实体关系模型)
ER模型通过实体(Entity)、属性(Attribute)和关系(Relationship)描述数据结构,常用于数据库设计。例如:
- 实体:订单(Order)、用户(User)。
- 属性:订单的“金额”、用户的“姓名”。
- 关系:一个用户可创建多个订单(一对多关系)。
与维度建模区别
- ER模型强调数据一致性,用于OLTP系统;维度模型优化查询性能,用于OLAP系统。
OLAP、OLTP 如何解释(区别)?三范式是什么,请举例说明。
OLAP vs OLTP
目标 | 支持复杂分析、数据挖掘 | 支持高并发事务操作(增删改查) |
数据量 | 海量历史数据 | 当前数据,规模较小 |
操作类型 | 批量读取、复杂聚合 | 短事务、单行操作 |
典型系统 | 数据仓库、BI工具 | 电商订单系统、银行交易系统 |
三范式
- 第一范式(1NF)字段不可再分。例如,将“联系方式”拆分为“电话”和“邮箱”:错误设计:user(id, contact),其中contact存储“电话,邮箱”。正确设计:user(id, phone, email)。
- 第二范式(2NF)消除部分依赖,确保非主键字段完全依赖主键。例如订单表:错误设计:orders(order_id, product_id, product_name, amount)(product_name依赖product_id而非主键order_id)。正确设计:拆分为orders(order_id, product_id, amount)和products(product_id, product_name)。
- 第三范式(3NF)消除传递依赖。例如用户表:错误设计:user(id, city, province)(province依赖city,city依赖id)。正确设计:拆分为user(id, city)和city_info(city, province)。
维度设计过程和事实设计过程是怎样的?
维度设计过程
- 识别维度从业务需求中提取分析视角(如“按时间、地区分析销量”对应时间、地区维度)。
- 定义维度属性确定维度表的字段,例如时间维度包含日期、周、季度、是否节假日。
- 处理缓慢变化维(SCD)根据业务需求选择处理方式:Type 1:覆盖旧值(适用于无需历史记录的场景)。Type 2:新增记录并标记有效期(保留历史版本)。
- 维度表优化使用代理键(自增ID)替代业务主键,避免依赖源系统ID变化。
事实设计过程
- 确定事实粒度明确每条记录的含义(如“每笔订单项”或“每日用户活跃数”)。
- 选择事实类型事务事实表:记录原子事件(如订单创建)。周期快照事实表:按固定周期汇总(如每日销售额)。
- 设计事实表结构包含维度外键和度量值,例如:
- 处理退化维度将常用维度字段(如订单号)直接存入事实表,避免关联查询。
- 聚合优化在DWS层预计算高频指标(如月销售额),减少查询计算量。
维度设计中有整合和拆分,有哪些方法,并详细说明。
维度设计的整合与拆分是解决数据冗余、提升查询效率的关键手段,具体方法如下:
整合方法
- 跨业务板块统一将不同业务线中含义相同的维度合并。例如,电商的“用户维度”与物流的“客户维度”可能均包含地址、联系方式,可整合为统一的dim_customer表。需处理字段冲突(如“手机号”字段名差异)并建立映射关系。
- 字段合并将多个相关字段合并为宽表。例如,将“年-月-日”三个字段合并为“日期维度表”,包含日期、周、季度等衍生属性。
- 代码值统一不同系统对同一枚举值的编码可能不同(如性别“男”在系统A编码为1,系统B编码为M),需转换为统一编码(如“男”映射为“MALE”)。
拆分方法
- 垂直拆分按字段使用频率拆分。例如,将用户维度拆分为dim_user_base(高频查询的姓名、性别)和dim_user_detail(低频的出生日期、职业)。
- 水平拆分按数据范围拆分。例如,将“时间维度表”按年份拆分为dim_time_2023、dim_time_2024,减少单表数据量。
- 属性分组拆分将大维度表按业务属性分组。例如,商品维度拆分为dim_product_category(类目信息)和dim_product_supplier(供应商信息)。
示例场景
- 整合:整合订单系统的“支付方式”与物流系统的“配送方式”为统一维度
dim_payment_type
,消除分析时的歧义。 - 拆分:用户表包含100个字段,将地址相关字段拆分为
dim_user_address
,提升查询性能。
事实表设计分几种,每一种都是如何在业务中使用?
事实表根据业务场景和数据处理方式分为以下类型:
事务事实表
- 特点:记录原子事件(如订单创建、支付成功),每条数据对应一个事务点。
- 业务应用: 电商平台记录每笔订单的创建时间、金额,用于分析实时交易趋势。日志系统记录用户点击事件,支持行为路径分析。
周期快照事实表
- 特点:按固定周期(日、周)汇总指标,如每日库存量、账户余额。
- 业务应用: 银行系统每日计算用户账户余额,生成snapshot_account_daily表。零售业统计门店每日销售额,生成日报。
累积快照事实表
- 特点:跟踪业务过程多个关键节点(如订单下单、发货、签收),记录各阶段时间与状态。
- 业务应用: 物流系统跟踪订单从“已发货”到“已签收”的全流程时效。保险理赔流程记录“报案”“审核”“赔付”等环节耗时。
无事实事实表
- 特点:仅记录事件发生,无度量值(如用户访问记录)。
- 业务应用: 记录用户登录事件,分析活跃时段分布。
类型对比
事务事实表 | 原子事件 | 仅插入 | 实时交易记录 |
周期快照 | 周期汇总 | 每日覆盖 | 库存、余额统计 |
累积快照 | 多节点流程 | 多次更新 | 订单全生命周期跟踪 |
单事务事实表、多事务事实表区别与作用是什么?
单事务事实表
- 定义:仅记录单一业务事件的事实表,如“订单创建”或“支付成功”。
- 结构:包含与该事件直接相关的维度和度量。
- 作用:支持精细化的单事件分析(如支付成功率)。
多事务事实表
- 定义:在同一表中记录多个关联业务事件(如“下单”“支付”“退款”)。
- 结构:每个事件对应独立的度量字段,可能包含多个时间戳。
- 作用:支持跨事件关联分析(如下单到支付的转化率)。
- 数据冗余:多事务表可能包含空字段(如未退款订单的
refund_time
为NULL)。 - 查询复杂度:多事务表减少关联查询,但需处理稀疏数据。
对比
请解释一致性维度、一致性事实、总线矩阵的概念。
一致性维度
- 定义:在不同数据集市或业务过程中,同一维度的属性和编码保持一致。例如,所有分析模型中的“时间维度”均包含“周数”“季度”且定义相同。
- 作用:确保跨主题分析时维度可关联(如销售与库存按统一时间维度聚合)。
一致性事实
- 定义:相同业务指标在不同模型中的计算逻辑一致。例如,“销售额”在订单事实表和促销事实表中均定义为“单价×数量-折扣”。
- 作用:避免同一指标因计算口径不同导致的分析结果冲突。
总线矩阵
- 定义:矩阵表格,横向列出业务过程(如“下单”“支付”),纵向列出公共维度(如时间、用户),标记各过程与维度的关联关系。
- 作用:指导数仓架构设计,确保维度可复用。例如,通过矩阵发现“用户维度”需被多个事实表共享,从而优先设计一致性维度。
示例
- 总线矩阵片段:
下单 | ✔ | ✔ | ✔ |
支付 | ✔ | ✔ | ✘ |
物流配送 | ✔ | ✔ | ✔ |
从 ODS 层到 DW 层的 ETL,做了哪些工作?
核心工作流程
- 数据清洗去重:删除重复记录(如日志重复采集)。补全:填充缺失字段(如用户性别未知时标记为“其他”)。纠错:修正异常值(如订单金额为负数时置为NULL)。
- 数据转换字段格式化:统一日期格式(如将“2024/01/01”转为“2024-01-01”)。计算衍生字段:根据出生日期计算年龄。代码值映射:将性别编码“1”“0”转换为“男”“女”。
- 维度退化将常用维度属性直接存入事实表,减少关联查询。例如,将“订单类型名称”冗余到事实表:
INSERT INTO dwd_orders SELECT o.order_id, o.amount, d.order_type_name -- 退化维度字段 FROM ods_orders o LEFT JOIN dim_order_type d ON o.type_id = d.type_id;
- 缓慢变化维(SCD)处理Type 1:直接更新维度属性(如用户地址变更覆盖旧值)。Type 2:新增维度记录并标记有效期(保留历史版本)。
- 数据聚合在DWS层预计算汇总指标。例如,按天统计销售额:
- 数据加载全量更新:每日覆盖目标表(适用于小数据量)。增量更新:通过时间戳或日志CDC捕获新增数据。
技术实现示例
- 处理SCD Type 2:
-- 新增维度记录 INSERT INTO dim_user SELECT user_id, '上海' AS address, CURRENT_DATE() AS start_date, '9999-12-31' AS end_date FROM ods_user_updates WHERE address_changed = 1; -- 关闭旧记录有效期 UPDATE dim_user SET end_date = CURRENT_DATE() - 1 WHERE user_id IN (SELECT user_id FROM ods_user_updates) AND end_date = '9999-12-31';
数据仓库的数据质量是怎么保证的,有哪些方法?怎么衡量数仓的数据质量,有哪些指标?
数据质量保障是数仓建设的核心环节,直接影响分析结果的可靠性,需从预防、检测、修复三个层面综合施策:
保障方法
- 数据清洗规则去重:通过唯一键约束(如订单ID)去除重复记录。补全缺失值:对NULL字段填充默认值(如未知地区标记为“其他”)。
- 约束检查主键唯一性:确保维度表主键不重复。外键约束:事实表的维度外键必须存在于维度表中。
- 数据标准化统一编码(如性别字段标准化为“男”“女”“未知”)。单位统一(如金额统一为人民币,汇率转换处理)。
- 血缘追踪与监控通过工具(如Apache Atlas)记录数据加工路径,定位异常源头。设置阈值告警(如订单量日环比下降超过30%触发告警)。
质量衡量指标
- 完整性:数据缺失比例(如日志采集丢失率≤0.1%)。
- 准确性:错误数据占比(如用户手机号格式正确率≥99.9%)。
- 一致性:跨系统指标差异(如订单数在ODS层与DWD层差异为0)。
- 及时性:数据延迟时间(如T+1任务完成时间≤凌晨3点)。
示例监控看板
数据缺失率 | (缺失记录数 / 总记录数) × 100% | ≤0.5% |
数据及时到达率 | (准时完成任务数 / 总任务数) × 100% | ≥99% |
增量表、全量表和拉链表分别是什么?
增量表
- 定义:仅存储新增或变更的数据,通常按时间分区(如
dwd_orders_20240501
)。 - 适用场景:数据量大的业务(如每日订单表),避免全量同步的资源消耗。
- 更新方式:通过日志(如MySQL Binlog)捕获增量数据。
全量表
- 定义:存储当前时间点的完整数据快照(如每日全量用户表
dim_user_full
)。 - 适用场景:数据量较小或需要全量分析的维度(如商品分类表)。
- 更新方式:每日覆盖或合并历史变更。
拉链表
- 定义:记录数据历史状态变化的表,通过
start_date
和end_date
标记有效期。 - 适用场景:跟踪缓慢变化维(如用户地址变更历史)。
- 结构示例: 1001北京2024-01-012024-05-311001上海2024-06-019999-12-31
对比
增量表 | 低 | 无 | 低 |
全量表 | 高 | 无 | 中 |
拉链表 | 中 | 高 | 高 |
数据仓库存储的基本要点(存储格式和压缩格式)是什么?
存储格式选择
- 列式存储(如Parquet、ORC)优点:适合OLAP查询(仅读取所需列),高压缩比。缺点:写入速度慢,不适合频繁更新。场景:DWD、DWS层事实表。
- 行式存储(如Avro、CSV)优点:适合整行读取或流式写入。缺点:查询性能低,压缩率低。场景:ODS层原始日志。
压缩格式选择
- Snappy:压缩速度块,适合实时写入(如Kafka数据落地)。
- GZIP:压缩比高,适合冷数据存储(如历史归档)。
- ZSTD:平衡压缩比与速度,适用于在线查询。
示例配置
-- 创建Parquet格式表并启用Snappy压缩 CREATE TABLE dwd_orders ( order_id INT, amount DECIMAL(10,2) ) STORED AS PARQUET TBLPROPERTIES ('parquet.compression'='SNAPPY');
数据仓库为什么要分层,数仓分层的架构是怎样的?
分层必要性
- 解耦:各层独立维护(如ODS结构调整不影响DWD)。
- 复用性:DWS层预聚合指标可被多个业务复用。
- 性能优化:通过分层减少重复计算(如ADS层直接读取汇总数据)。
分层架构
- ODS(操作数据层)职责:存储原始数据,保留业务系统表结构。技术选型:HDFS、Hive表(行式存储)。
- DWD(明细数据层)职责:清洗、标准化、维度退化后的明细数据。技术选型:Parquet/ORC列式存储,分区优化。
- DWS(汇总数据层)职责:预计算指标(如用户月活、商品销量Top10)。技术选型:ClickHouse、Doris等OLAP引擎。
- ADS(应用数据层)职责:面向业务的数据集市(如报表、API接口)。技术选型:MySQL(高频查询)、Redis(缓存)。
数据仓库设计中的要点和难点分别是什么?
设计要点
- 需求驱动深入理解业务目标(如分析用户留存需跟踪登录行为)。
- 模型可扩展性预留扩展字段(如事实表添加reserved_col1)。
- 数据治理制定命名规范(如事实表前缀fact_,维度表前缀dim_)。
设计难点
- 数据一致性跨系统数据合并时处理编码冲突(如订单状态在不同系统的定义不同)。
- 性能与成本平衡预聚合过多导致存储成本上升,需根据查询频率动态调整(如仅聚合高频指标)。
- 历史数据回溯处理SCD时需兼顾存储效率与查询性能(如拉链表分区策略优化)。
示例解决方案
- 一致性维度:建立企业级维度中心,强制所有团队使用统一维度表。
- 性能优化:对万亿级事实表采用分区分桶(如按日期分区+user_id分桶)。
是否了解维度建模?请简述维度建模的基本概念。维度建模主要解决什么问题?
维度建模是一种面向分析场景的数据仓库设计方法,核心目标是通过优化数据结构提升查询性能与分析效率。其基本概念围绕事实表与维度表构建:
- 事实表:记录业务过程的可度量数值(如订单金额、点击次数),包含外键关联维度表。
- 维度表:描述业务过程的上下文属性(如时间、用户、商品),提供筛选与分组条件。
模型类型
- 星型模型:事实表直接关联多个维度表,结构简单,适合高性能查询。
- 雪花模型:维度表进一步规范化(如地区维度拆分为国家、省份表),减少冗余但增加查询复杂度。
解决的问题
- 性能瓶颈:传统范式建模(OLTP)多表关联导致查询延迟,维度建模通过冗余维度属性减少关联次数。
- 分析友好:预关联的星型模型支持快速上卷(Roll-up)与下钻(Drill-down)操作。
- 业务理解成本:直观的模型结构降低业务人员使用门槛(如直接筛选“地区=北京”分析销售额)。
示例
- 电商场景:订单事实表关联用户维度(地区、年龄)、商品维度(类目、品牌),支持多维分析。
- 对比范式建模:维度建模的订单表冗余用户地址,避免关联用户表,查询性能提升10倍以上。
数仓分主题预计算的好处和坏处是什么?
分主题预计算指在数仓中按业务主题(如销售、用户行为)预先聚合指标,其优缺点如下:
好处
- 查询性能优化:避免实时计算海量明细数据。例如,预计算“每日用户活跃数”可直接查询,无需全表扫描。
- 业务响应加速:报表系统直接读取预计算结果,响应时间从分钟级降至秒级。
- 资源节省:减少重复计算(如多个报表共用同一汇总表)。
坏处
- 存储成本增加:预计算表占用额外空间(如日、周、月多级聚合)。
- 灵活性受限:预计算指标无法动态适配新维度(如新增“用户年龄段”需重新聚合)。
- 数据更新延迟:T+1预计算无法支持实时分析需求。
场景示例
- 好处场景:电商大促期间,预计算“实时销售额Top10商品”快速展示战报。
- 坏处场景:用户临时需要“按小时粒度分析访问量”,预计算表仅支持天粒度,需临时扫描明细数据。
平衡策略
- 分层预计算:在DWS层存储常用聚合(如日粒度),保留明细数据供特殊需求使用。
- 动态聚合:通过OLAP引擎(如Doris)支持按需聚合,平衡性能与灵活性。
指标维度矩阵了解吗?
指标维度矩阵是数仓设计中的工具,用于系统性规划指标与维度的关联关系,确保模型可扩展性与一致性。
核心元素
- 指标:可度量的业务数值(如销售额、用户数)。
- 维度:分析视角(如时间、地区、产品)。
矩阵表示例
销售额 | ✔ | ✔ | ✔ | ✘ |
DAU | ✔ | ✔ | ✘ | ✔ |
作用
- 识别缺失:检查指标是否覆盖所有必要维度(如“DAU”缺少产品维度,需补充)。
- 一致性设计:确保相同维度在不同指标中的定义一致(如“地区”均包含省、市两级)。
- 需求优先级:高频维度组合优先落地(如“时间+地区”销售额聚合)。
应用场景
- 模型评审:通过矩阵验证是否支持业务部门的分析需求。
- 跨团队协作:指导ETL开发人员明确指标计算逻辑与维度关联关系。
你觉得怎样判断一个数据明细模型是否算做一个好的数据明细模型?
优秀的明细模型需满足以下核心标准:
数据完整性
- 字段覆盖:包含业务分析所需的全部字段(如订单表需有金额、状态、时间)。
- 数据粒度:保留原子粒度(如订单项级别而非订单汇总),支持下游灵活聚合。
模型可读性
- 命名规范:字段名与表名清晰表达业务含义(如
user_age
而非col_12
)。 - 注释完备:通过文档或元数据描述字段计算逻辑(如“销售额=单价×数量-折扣”)。
性能与扩展性
- 分区策略:按时间或业务键分区(如
order_date
),优化查询效率。 - 字段冗余:适度退化高频维度属性(如将“商品名称”冗余至事实表,减少关联查询)。
示例对比
- 差模型:
fact_order
表缺失“支付方式”字段,无法分析支付渠道贡献。 - 好模型:
fact_order
包含订单金额、用户ID、商品ID、支付方式,并分区按order_date
。
验证方法
- 业务验证:确认模型支持核心分析场景(如用户留存率计算)。
- 性能测试:大数据量下查询响应时间符合SLA(如95%查询<5秒)。
数仓指标同名不同义的解决方法?
同名不同义(如“销售额”在A部门指GMV,在B部门指净收入)会导致数据误解,需通过治理手段解决:
统一命名规范
- 前缀区分:按业务线或模块命名(如
finance_revenue
与sales_gmv
)。 - 层级定义:通过命名空间划分(如
dws_finance.sales_amount
vsdws_sales.sales_amount
)。
元数据管理
- 数据字典:记录指标的计算公式、数据源与责任人。
- 血缘追踪:通过工具(如Apache Atlas)展示指标加工路径,明确来源差异。
流程管控
- 评审机制:新增指标需经过数据治理团队审核,避免重复定义。
- 版本管理:对指标变更记录历史版本(如
sales_amount_v2
)。
示例场景
- 问题:财务与销售部门“销售额”定义冲突。
- 解决:重命名为
finance_net_sales
与sales_gross_sales
,并在数据字典中注明差异。
17年+码农经历了很多次面试,多次作为面试官面试别人,多次大数据面试和面试别人,深知哪些面试题是会被经常问到。 在多家企业从0到1开发过离线数仓实时数仓等多个大型项目,详细介绍项目架构等企业内部秘不外传的资料,介绍踩过的坑和开发干货,分享多个拿来即用的大数据ETL工具,让小白用户快速入门并精通,指导如何入职后快速上手。 计划更新内容100篇以上,包括一些企业内部秘不外宣的干货,欢迎订阅!