面灵AI→

虎牙数据开发一面:数仓分层、缓慢变化维与数据倾斜

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 先做一下自我介绍。
  2. 讲一下这套数仓的数据源、分层作用、表设计与血缘依赖,说明整体设计思路。
  3. 维度表一般包含哪些字段?举两个例子。
  4. 部门、项目会发生组织变动,你如何处理缓慢变化维?
  5. 维度表有没有按日期做快照?
  6. DWS 层采用什么粒度?举一个明确粒度的例子。
  7. 比率类衍生指标是在 DWS 层计算完成吗?
  8. DQC 校验的设计原则与规则是什么?
  9. 讲一个链路优化、解决数据倾斜的真实案例。
  10. 和业务对齐指标时,你最关键要拿到哪些信息?
  11. 开发结果有没有和业务预期不一致的情况?
  12. 任务产出时效能否满足业务要求?
  13. 项目结束有没有沉淀交付文档?
  14. 简历没有写实时任务,实时开发是自学的吗?
  15. 离线开发主要用 Spark + Hive 吗?查询引擎也是 Spark 吗?BI 展示层有没有 MPP 加速引擎?
  16. 介绍几种 SQL Join 方式以及区别。
  17. 反问:岗位轮次、团队规模与职责、团队内部 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(小数据量或非等值条件)。