虎牙数据开发一面:数仓分层、缓慢变化维与数据倾斜
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 先做一下自我介绍。
- 讲一下这套数仓的数据源、分层作用、表设计与血缘依赖,说明整体设计思路。
- 维度表一般包含哪些字段?举两个例子。
- 部门、项目会发生组织变动,你如何处理缓慢变化维?
- 维度表有没有按日期做快照?
- DWS 层采用什么粒度?举一个明确粒度的例子。
- 比率类衍生指标是在 DWS 层计算完成吗?
- DQC 校验的设计原则与规则是什么?
- 讲一个链路优化、解决数据倾斜的真实案例。
- 和业务对齐指标时,你最关键要拿到哪些信息?
- 开发结果有没有和业务预期不一致的情况?
- 任务产出时效能否满足业务要求?
- 项目结束有没有沉淀交付文档?
- 简历没有写实时任务,实时开发是自学的吗?
- 离线开发主要用 Spark + Hive 吗?查询引擎也是 Spark 吗?BI 展示层有没有 MPP 加速引擎?
- 介绍几种 SQL Join 方式以及区别。
- 反问:岗位轮次、团队规模与职责、团队内部 AI 工具落地情况。
《参考解析》
数仓分层与血缘:ODS 贴源(几乎不做加工,保留原始快照与变更)、DWD 明细(清洗、去重、统一口径、做维度关联,粒度是「一行一个业务事件」)、DWS 汇总(按主题与时间粒度预聚合,一行是「某主体在某周期内的汇总」)、ADS 应用层(面向具体报表与接口)。分层的目的不是好看,而是让变更的影响范围可控:口径变了改 DWD、报表需求变了改 ADS,中间层不动。血缘的价值在于影响分析——上游表字段变更时能立刻知道哪些下游会坏。
维度表与缓慢变化维:维度表典型字段是代理键 + 业务主键 + 名称 + 层级/分类 + 生效/失效时间 + 是否当前版本。缓慢变化维的处理分几种:SCD1 直接覆盖(不保留历史,简单但丢历史)、SCD2 拉链表/多行版本(加 start_date/end_date/is_current,能回溯任一时刻的状态)、SCD3 加一列存「上一个值」(只保留有限历史)。组织架构变动必须用 SCD2,否则按历史日期统计的部门维度会错。按日期做快照是另一种常见方案(每天存一份全量维度),查询简单、存储大,适合维度变化频繁且查询时效敏感的场量。选择时要说明存储成本 vs 查询复杂度的取舍。
DWS 粒度与比率指标:DWS 的粒度是「维度组合 + 时间周期」,比如「天 + 直播间 + 设备类型」就是一行。比率类指标的原则是在 DWS 存分子分母(或可加和的度量),不要在 DWS 存比率本身——因为比率不可加,跨天/跨维度汇总时直接加会算错。ADS 层再按需要的口径计算比率。
DQC 的设计原则:分四类规则——完整性(主键非空、分区行数波动超阈值)、唯一性(主键/业务键重复)、有效性(枚举值域、日期格式、金额范围、关联键能在维表找到)、一致性(父子表数量对得上、汇总值等于明细求和)。原则是:规则要能自动跑、失败要能定位到具体分区与责任表、告警要分级(阻断 vs 提示),并且规则本身要随业务演进,否则要么天天误报被忽略、要么漏掉真问题。
数据倾斜的实战案例:典型成因是大 key(某个主播/某类设备占了绝大部分数据)或空值集中。处理手段按代价排:先过滤/单独处理空值与异常大 key;再考虑加盐打散(给热点 key 加随机后缀先局部聚合再二次聚合);或者用 map-side join 广播小表避免 shuffle;还可以调参(增大并行度、开 skew join)。回答时要给出「倾斜前后的任务时长/数据分布」对比,只讲方法不给结果会被追问。
和业务对齐指标要拿到什么:口径定义(分子分母、去重逻辑、时间边界)、数据来源(哪个系统是权威源)、更新频率与产出时间、异常处理(退款/撤销怎么算)、以及验收方式(业务拿什么数来核对)。最容易出问题的是时间口径(自然日 vs 滚动 24 小时)和去重口径(人次 vs 人数)。
SQL Join 方式:内连接(只保留匹配)、左/右外连接(保留一侧全部)、全外连接(两侧都保留)、交叉连接(笛卡尔积,慎用)、半连接(EXISTS/IN,只判存在不取列)、反连接(NOT EXISTS,取不存在)。执行层面还有 hash join(大表对小表,建哈希表)、sort-merge join(两表都大且有序)、broadcast join(小表广播到每个 executor,避免 shuffle)、nested loop(小数据量或非等值条件)。