公司动态

B站数仓校招笔试复盘:从维度建模到订单分析的设计思路

📅 2026/8/31 6:44:49
B站数仓校招笔试复盘:从维度建模到订单分析的设计思路
1. B站数仓校招笔试的出题逻辑考的不是SQL语法是建模思维先聊聊这张卷子给我的整体感受。严格来说哔哩哔哩2023校园招聘数据仓库方向的笔试题和市面上绝大多数“大数据刷题平台”上能刷到的题有很大区别。市面上很多题库侧重让你写一个复杂的SQL考窗口函数、考调优技巧但B站这套卷子明显更关注你对数据仓库本身的认知框架——从业务需求到模型设计从数据治理到稳定性保障它更像是一张“数据仓库工程师岗位的专业素养摸底卷”而不是一张“SQL语法竞赛卷”。我个人认为这种出题逻辑和B站的数据业务形态有直接关系。B站是一个以UGC内容为核心的视频社区数据链路非常长用户行为、稿件生产、内容消费、互动关系、商业化广告、会员购电商甚至直播和游戏联运这些业务域的数据几乎全部要汇入数据仓库。数仓团队面临的核心挑战不是怎么写出一个跑得动的SQL而是怎么在高速迭代的业务中设计一套能稳定支撑分析需求、又不至于让模型膨胀到不可维护的数据架构。这种现实压力自然会折射到校招笔试卷子上面试官想看的是一个刚出校门的人有没有建立从“业务问题”到“数据模型”的翻译能力。另外B站作为内容社区数据还有一个显著特点数据量大但单条价值密度低强实时性需求和多维度交叉分析需求并存。比如一个视频的播放量、点赞数、投币数这些指标看起来简单但一旦要按分区、按用户画像、按时间维度去分析模型设计的好坏直接影响查询效率和口径一致性。笔试题目里那些看似基础的概念题——维度表、事实表、拉链表、缓慢变化维——其实都是在考察你有没有能力应对这种“简单指标背后的复杂建模”问题。所以在开始逐题复盘之前我建议大家先调整心态不要指望靠刷题来应付这类试卷你需要的是把数据仓库的核心理论真正吃透并且能用自己的话讲清楚每个设计决策背后的理由。这篇文章我会按照试卷考察的知识模块把高频考点、典型题目、以及我在实际项目中踩过的坑完整拆开来讲。2. 从试卷结构看数仓岗位的能力要求四类题目背后的真实工作场景先说一个整体结构判断。虽然具体的试卷题目每年会变但数据仓库方向的校招笔试基本上稳定在四个大类之间轮转我把它们拆开来看每一类背后都对应真实工作场景中的一项核心技能。2.1 SQL与数据处理能力这不是在考语法是在考你能否处理“脏数据”第一类是SQL编写与数据处理题。这类题表面上是给你一个业务场景比如“统计连续三天活跃的用户”“计算每个视频发布后7日播放留存率”实际上考察的是你面对真实数据时的处理能力。很多同学一看到这类题就开始背窗口函数的写法这其实是个误区。真实的数仓开发工作里SQL写得好不好并不取决于你会不会用LAG、LEAD、ROW_NUMBER这些函数——当然这些是基本功——而在于你写出的SQL能不能应对数据质量的问题。比如数据里出现了重复记录你的统计口径会不会被污染某些分区数据延迟到达你的任务是不是能优雅处理空窗口用户ID存在多种登录方式手机号、邮箱、第三方授权你关联时会不会产生数据膨胀我在实际工作中就遇到过一次典型的“数据膨胀事故”。当时统计一个广告投放报表事实表按用户ID关联维表结果用户维表里因为历史数据合并同一个用户ID出现了两条记录关联出来的结果直接翻倍。上线一周后业务方才发现数据不对。这个问题如果在笔试中就考察你“关联前要不要先去重”的意识很多人是答不出来的。所以我的建议是准备这类题的时候不要只刷“纯函数题”一定要练习那些夹杂了数据清洗、去重、空值处理、缓慢变化维读取逻辑的复合型SQL题。这类题才是真正贴近数仓日常工作场景的。2.2 数据建模理论题维度建模是整个数仓岗位的“立身之本”第二类是数据建模理论题这也是B站这类互联网公司最看重的部分。考察范围基本围绕维度建模的核心理念展开星型模型和雪花模型的区别、事实表的三种类型事务事实表、周期快照事实表、累计快照事实表、维度表的设计原则、缓慢变化维的处理策略、退化维度、代理键和自然键的概念等等。这些概念听起来是教科书里的条条框框但在B站实际业务里每一条都有非常具体的落地场景。就拿事实表来举例事务事实表比如用户每产生一次播放行为就记录一行。这种表记录的是“动作”适合做各种维度的切片分析但数据量会非常庞大。周期快照事实表比如每天记录一次用户的累计观看时长。这种表记录的是“状态”适合做存量分析但无法回溯历史动作细节。累计快照事实表比如一条记录从订单创建开始记录下支付时间、发货时间、完成时间等多个业务节点。这种表适合做业务流程的时效分析比如从下单到支付要多久从支付到发货要多久。笔试中如果给你一个订单业务场景让你设计事实表和维度表本质上就是在考察你有没有能力根据分析需求选择合适的表类型和粒度。核心决策顺序几乎永远是先确定业务过程再确定粒度然后确定维度最后确定事实。这个顺序不能乱。我见过很多候选人一上来就画表结构连“这个事实表到底记录哪个业务过程”都没说清楚这种回答基本上是被一票否决的。2.3 数仓架构与数据治理题分层设计、同步策略和血缘关系第三类题考察的是你对数仓整体架构的理解比如数据分层ODS、DWD、DWS、ADS比如从业务库到数仓的数据同步方式全量同步、增量同步、拉链表再比如数据血缘、数据质量监控、元数据管理这类数据治理相关的内容。这类题目的难度在于它不仅仅是背概念就能答好的。面试官通常会给你一个具体的业务场景让你做一个架构选型决策。比如“业务库表数据量比较大每天有新增和变更你怎么把它同步到数仓”这个时候你只回答“用增量同步”是不够的你还需要说清楚增量同步的前提是源表有变动时间字段如果源表是物理删除增量同步还能同步删除记录吗如果每天同步一次业务方凌晨修改了昨天的数据第二天报表出来以后你是覆盖还是追加如果要支持历史数据回溯是不是需要考虑拉链表方案拉链表和全量分区表各自的优缺点是什么这些问题的背后考察的是你有没有系统性地考虑过“数据从产生到可被分析消费”的完整生命周期。在B站这种业务快速迭代的公司每天都有大量的临时需求需要支持如果数仓架构设计得不合理任何一个环节掉了链子数据团队就得紧急救火。2.4 业务理解与场景设计题给你一个业务问题你怎么拆解成数仓方案第四类题是业务理解与场景设计题这往往是整张试卷里分值最高、淘汰率也最高的部分。题目一般会给你一个看似开放的问题比如“B站想分析不同分区的用户活跃情况请你设计一套数仓方案”或者“如何评估一次会员购大促活动的效果”。这类题考察的核心是你面对一个模糊业务问题时能否快速把它拆解为可落地的数据需求并且能够识别出关键指标和关键维度。我给大家分享一个答题框架是我在实际工作里总结出来的无论遇到什么业务场景题都可以套用明确业务目标先问自己这个分析做出来业务方要拿去干什么是评估业绩、指导运营、还是诊断问题拆解核心指标从业务目标倒推哪些指标能反映这个目标比如大促效果评估至少要有GMV、订单量、客单价、拉新数量、复购率等。梳理分析维度这些指标要从哪些角度去看时间分时/分日/分周、内容分区、用户层级、新老用户等。确定数据粒度与模型每张事实表对应哪个业务过程粒度是什么关联哪些维度表是否需要预先聚合。补充数据链路的可实现性这些数据从哪里来是埋点还是业务库埋点缺失怎么补口径不统一怎么办这个框架看起来简单但绝大多数应届生是答不完整的。很多人一上来就抓着SQL实现细节不放却忽略了业务目标本身——这就是典型的“捡了芝麻丢了西瓜”。面试官想看到的是你能够站在业务方的视角去思考数据问题的完整链路而不是一个只会写代码的“执行者”。3. 用户订单分析数仓设计题拆解维度表和事实表的“标准答案”思路关于用户订单分析的数仓设计题是历年校招笔试中出现频率极高的一道题也是网络热词中特别点到的内容。我把它单独拿出来详细拆解——因为这道题几乎就是数据建模能力的“试金石”。表面上看它考察的是你会不会建表往深了说它考察的是你对业务本质的理解、对粒度的把控、以及对维度模型优化能力。3.1 第一步必须是确定业务过程和粒度而不是先画表很多第一次接触这道题的同学第一反应往往是“订单表就是一堆字段嘛用户ID、商品ID、订单金额、下单时间……”然后就开始列字段了。如果你在笔试里这么做基本就落入了陷阱。正确的打开方式是先明确你设计这套模型要支撑什么分析需求。同样是用户订单数据支撑财务结算和支撑用户增长分析模型设计出来是完全不一样的。我们假设分析需求是“从多个维度分析用户的订单行为比如按用户属性、商品类目、下单时间来看订单量和GMV的变化趋势同时要能看到每个订单的明细与状态流转情况。”基于这个需求业务过程就很清晰了用户下单购买商品。这个业务过程包含的事实可以是订单金额、商品数量、运费、优惠金额等。那么事实表的粒度是什么这里存在一个经典选择粒度定到订单头一个订单一行优点是简单直观但缺点是一个订单包含多个商品时无法按商品维度分析。粒度定到订单明细行订单商品一行优点是支持商品维度分析缺点是一个多商品订单会产生多行聚合到订单粒度时要小心去重。粒度定到订单明细子维度订单商品SKU促销活动最为灵活但数据量膨胀明显。我的建议是如果没有特殊说明优先选择“订单明细行”作为事实表的粒度。因为在实际互联网业务里“按商品维度分析”几乎是必备需求。而为了兼顾“订单视图”可以在DWS层做一张按订单粒度聚合的汇总表这样可以各取所长。3.2 订单事实表的具体设计事实、可加性、退化维度确定粒度之后我们来拆事实表的字段设计。先放一张我在实际项目中常用的订单明细事实表结构供大家参考字段类别字段示例设计要点业务事实订单原价金额、实付金额、商品数量、优惠金额、运费事实字段必须是可加的并且要区分“半可加事实”如优惠金额按订单可加但跨订单商品维度不可简单累加退化维度订单ID、订单状态、下单渠道直接存在事实表中不单独建模为维表减少关联开销外键维度用户ID、商品ID、商家ID、店铺ID、类目ID、下单日期ID这些外键指向独立的维度表时间字段下单时间、支付时间、发货时间、完成时间如果是订单级多节点优先用累计快照事实表来建模唯一键订单ID商品ID行号保证事实表内没有重复记录这直接影响统计准确性关于事实字段我想多说一句。很多教科书里会强调“事实必须是可加的”这个原则在笔试里也是高频考察点。但你得理解得更深一层像“单价”这种字段——它是不可加的两个订单的单价相加没有业务意义——这种字段就不应该作为事实字段放进去而应该拆到其他维度表或作为派生字段在SQL查询时计算。还有“折扣率”这类半可加事实它可以在订单粒度累加后求加权平均但不能简单累加。如果笔试中你能主动指出字段的“可加性”问题面试官对你的评价会明显不一样。3.3 用户维度表设计不能只放一个UserID就完事用户维度是几乎所有分析场景都绕不开的核心维度。但在笔试设计题里很多同学对用户维度的处理都过于粗糙只写了个“用户ID、注册时间、用户等级”就结束了。这远远不够。一个好的用户维度表应该能支撑起对用户的多视角分析。我一般会把它分成几类字段身份类用户ID、注册时间、注册渠道、手机号脱敏、性别、年龄段属性类会员等级、是否大会员、用户类型普通用户/UP主/商业合作行为概要类近30天登录天数、近30天观看时长、累计投币数实时性要求高的话这类字段往往放在用户标签系统里而不是维度表分层类用户生命周期阶段新用户/活跃用户/沉默用户/流失用户、价值分层高价值/中价值/低价值。这里有个很重要的设计原则也是笔试中容易踩坑的点维度表应该描述“状态”而不是描述“动作”。比如说“最近一次下单时间”这个是状态字段可以放但“每一笔下单的具体时间”那是事实应该放在事实表里。维度表字段的冗余设计是在合理范围内的——比如把用户年龄段和性别冗余到用户维度表这没问题因为它们是低频变化的属性。但如果把用户每天的行为次数这种高频变化的度量也塞进用户维度表这张表的更新效率会变得非常差这在笔试中属于典型的“设计错误”。另外如果你是做“用户订单分析”用户维度表和订单事实表之间通常是一对多的关系。这个在ORM或SQL关联上体现得比较直观但在建模时你可能需要考虑是否需要对用户维度做退化处理——也就是把用户ID以及常用的用户属性直接冗余到事实表里这样查询的时候可以减少一次JOIN。但是冗余会带来一致性问题如果用户属性变更历史订单数据里的冗余字段要不要跟着变这就是接下来要讲的“缓慢变化维”问题。3.4 商品维度、时间维度和订单状态维度别忽略这些“配角”用户维度常常是大家关注的重点但商品维度、时间维度这些“配角”维度才是实际数据处理中的隐藏坑点。商品维度的典型字段包括商品ID、商品名称、类目ID、类目名称、品牌、价格、上架时间、下架时间、商品状态。设计商品维度时最棘手的问题是类目层级。B站的会员购商品可能有多级类目划分一级类目、二级类目甚至三级类目。笔试中你至少应该提到两种处理方式方式一在商品维表里冗余多级类目字段一级类目ID、二级类目ID、三级类目ID简单直观查询方便方式二单独建立类目维度表商品表只挂一个最细层级的类目ID通过多次JOIN往上卷。这种方式更规范但查询时如果不知道类目层级深度写SQL会非常痛苦。在实际项目里我倾向于方式一配合DWS层按各级类目预先聚合汇总数据这样既保证了灵活性又兼顾查询性能。在笔试答案里你两种方案都可以提重点是要说清楚各自的取舍这样能体现出你真的理解建模的权衡而不只是死记硬背。时间维度很多同学会忽略觉得查询的时候直接DATE_FORMAT不就完了吗但如果数仓里所有的事实表都直接存业务时间戳每次聚合都要做一次时间格式转换查询效率会很低而且不同表中时间粒度不一致也会造成口径混乱。更规范的做法是单独建立一张时间维度表包含日期、周几、是否节假日、是否工作日、所属月份、所属季度、所属年份等属性。事实表里存日期ID如20230101关联时间维表直接切片。这个设计在笔试里提到属于标准的加分项。订单状态维度这个比较有意思。订单不是一个一次性事件它有状态流转——待支付、已支付、已发货、已完成、已取消、已退款等等。这时候你就要考虑使用累计快照事实表把同一个订单从创建到完成或取消的所有关键时间节点都记录在同一行里。这样做的好处是分析“订单从支付到发货平均耗时多久”“有多少订单卡在待发货超过24小时”这类问题会非常高效因为这些交叉状态指标不需要多张表JOIN直接在一行里就能算出来。3.5 缓慢变化维SCD订单分析里最容易被追问的知识点很多同学笔试能通过但在面试环节挂在缓慢变化维上。真实业务中用户的下单地址变了、商品的类目调整了、店铺的所属负责人换了——这些都意味着维度表里的属性发生了变化。问题是历史订单事实表关联维度表时应该关联到变更前的属性还是变更后的属性这是数仓建模里最经典的“缓慢变化维”问题也是我在实际工作中被业务方挑战最多的地方。处理策略主要有四种笔试答题时要能讲清楚各自适用场景策略处理方式优点缺点常见适用场景SCD1直接覆盖旧值简单无法回溯历史错误修正、低价值属性SCD2新增一行标记生效时间和失效时间保留完整历史数据量膨胀、关联变复杂用户等级、商品类目调整SCD3保留当前值和历史值两个字段查询方便只能保留一次变更历史地址变更、负责人变更SCD4用单独的历史表存储变更记录当前表保持简洁查询逻辑复杂极少使用在用户订单分析场景里最需要注意的其实是用户收货地址和商品归属类目这两个维度属性。举个例子一个商品从“数码”类目挪到了“家电”类目如果不用SCD2策略直接覆盖类目那么历史上所有在该商品未调整类目之前的订单如果做类目维度分析都会被算到新类目下面导致历史对比失真。但如果使用SCD2每次类目变更都生成一条新记录事实表在关联时还要加上“关联时间点在生效区间内”的条件才能取到正确的属性快照。这个场景如果在笔试里能主动讲出来再配合一句“订单分析中时间旅行查询time travel是真实存在的需求”面试官基本会认为你是真的做过数仓项目的而不是只会背教材。4. 数仓分层架构和调度依赖设计题里必须答出的“隐性考点”用户订单分析的建模题本身已经能考察很多维度了但B站的笔试卷往往会在这个题目基础之上再加一问“请描述你设计的数仓分层结构以及各层之间的数据流转方式。”这一问就是典型的隐性考点考察你是否具备整体架构思维。4.1 ODS、DWD、DWS、ADS四层结构的职责边界标准的互联网数仓分层一般分为四层ODS操作数据存储层、DWD数据明细层、DWS数据汇总层和ADS应用数据服务层。我把各层的职责边界和设计要点整理一下。ODS层核心任务是“原样接入、保留痕迹”。从业务库同步过来的数据尽量不做清洗转换只做最简单的增量/全量识别和格式规范化。ODS层的作用是数据追溯——如果DWD层出了数据问题可以从ODS层重新跑数。这一层表结构和源系统几乎是一一对应的所以不需要做太多模型设计。DWD层这是数仓建模最核心的一层主要负责清洗、标准化、维度退化、以及生成明细事实表。这里做的才是真正的维度建模工作。用户订单分析里的订单明细事实表就应该建立在DWD层。同时DWD层往往要处理多源数据合并的问题——比如订单数据一部分来自交易库一部分来自订单中间件日志这中间就涉及到数据一致性、幂等性的校验。DWS层这一层做的是“公共汇总”。它服务于所有需要多维统计分析的下游需求。比如针对订单业务可以按“用户日汇总”“商品日汇总”“类目日汇总”三个维度做预聚合表。为什么需要这一层因为如果每次业务方跑一个“按天统计各分区GMV”的分析都要从DWD层的全量明细数据去扫那是巨大的计算浪费。DWS层通过预聚合把高频查询需求提前算好查询响应速度可以提升几个数量级。ADS层这一层是针对具体应用场景的定制数据比如报表专用的结果表、BI工具的数据源、推荐算法特征表等。ADS层可以非常灵活不需要严格遵循范式甚至可以一张表只服务一个报表。在笔试时如果你能把每一层的职责边界讲清楚并且用订单分析这个场景来举例说明每一层分别包含什么表基本上就达到架构题的满分线了。我见过很多答案直接把教科书里的分层理论搬上来——ODS是什么、DWD是什么——背得头头是道但完全无法结合题目场景来说明。这种答案在阅卷人眼里和没答一样。4.2 任务调度与数据依赖笔试里不常考但实际工作中天天踩的坑数据仓库的另一个核心问题是任务调度和数据依赖。虽然这个主题在校招笔试中的显性占比不高但如果在架构设计题里提到“数据流转方式”难免会涉及调度依赖的设计。我举个典型的例子。订单DWS层按日汇总表依赖于DWD层订单明细表的当天分区DWD层订单明细表又依赖于ODS层订单业务数据当天的增量分区。这个依赖链如果构建不当比如ODS任务已经跑完了但DWD层因为上游数据质量问题还没出数那么下游的任务是等待重跑还是报警挂起这背后其实是对“数据任务依赖体系”设计能力的考察。实际项目中我最常用的调度策略是逐层依赖、失败重试、阻塞告警三个机制配合使用逐层依赖每层任务只依赖上游任务的完成节点不要跨层依赖。比如DWS任务依赖DWD任务完成后触发而不是依赖ODS完成后的固定时间触发。这样可以保证下游等到的永远是“数据就绪”信号。失败重试对于偶发的数据延迟或网络抖动设置2到3次重试重试间隔可以递增加长比如5分钟后重试第一次、15分钟后重试第二次。阻塞告警如果重试超过次数上限任务进入阻塞状态并自动发出告警通知值班同学介入而不是默默失败或者永久挂起。在笔试答案里你不需要写得这么细但至少应该提到“数仓任务之间是有依赖关系的下游任务的启动条件是上游任务的完成而不是固定时间点”。这个认知能帮你和那些只会写SQL的候选人拉开差距。4.3 全量同步、增量同步与拉链表数据同步方案的取舍再展开说一下数据同步方案因为这也是笔试中频繁出现的知识点而且在用户订单分析场景里订单表和用户表的数据特性差异很大需要选择不同的同步策略。先说全量同步。最直观每天把整张表覆盖式同步到数仓。优点是实现简单数据一致性好缺点是随着数据量增长后期代价巨大。适合数据量小或者变化不频繁的表比如类目表、区域配置表。再说增量同步。每天只同步新增和变更的数据。优点是同步效率高缺点是要处理变更捕获CDC的逻辑。比如通过源表的时间戳字段识别增量还是通过日志解析如Canal订阅MySQL binlog如果只靠时间戳源表删除数据时是无法感知的如果需要记录删除操作必须依赖日志解析。这个知识点在笔试中如果能主动展开也是明显的加分项。最后重点说拉链表。这是数仓中兼顾存储成本和历史追溯的一种方案我强烈建议校招同学一定要掌握。拉链表的核心思想是每一行记录都有一个生效开始日期和一个生效结束日期。当用户的某个属性如用户等级发生变化时不是覆盖老记录而是把老记录的结束日期更新为昨天再插入一条新记录开始日期为今天。查询某个时间点上的历史快照时只需要判断“查询日期在开始日期和结束日期之间”即可。拉链表在B站这类业务场景中应用非常广泛。比如大会员用户的状态、UP主的分区归属、稿件的审核状态这些都是高频变化但又不是每时每刻都在变的属性非常适合用拉链表来建模。笔试中如果你能在设计维度表时提到“用户等级这种变化频率不高的属性我建议用拉链表实现”阅卷人对你的评价会高出好几个档次。5. SQL手写题的高频场景连续活跃、留存漏斗、累计聚合数据仓库笔试除了建模和架构题SQL手写题基本上也是必考环节。B站2023这套卷子里的SQL题据我了解主要围绕内容平台的核心分析场景展开我挑几个高频类型结合真实业务场景把解题思路和易错点讲透。5.1 连续N天活跃用户统计这题的考点不是窗口函数是去重思想“统计连续3天活跃的用户”几乎是所有数仓笔试的保留题目。看似简单但能一次做对的人并不多。最规范的解法思路是这样先按用户和活跃日期去重确保一个用户一天只保留一条记录因为一个用户一天可能有多次活跃行为如果用原始行为表直接算会出现重复计算导致的连续判断错误然后用窗口函数给每个用户按日期排序计算日期和行号的差值——如果用户是连续活跃的那么“活跃日期减去行号”这个差值应该是同一个值最后按用户和差值分组统计记录数如果记录数大于等于3就说明该用户存在至少一个连续3天的活跃区间。这个思路里最核心的两个点一是必须先做日期去重这对应了真实数仓SQL开发中“数据质量校验”的意识二是理解“日期减去行号”为什么能识别连续区间。很多同学知道这个公式但不理解背后的原理一旦题目改成“连续3天不活跃用户”就容易懵。如果你在笔试时能在答案里主动加上一句“首先对用户活跃日期去重避免同一用户当天多条活跃记录导致重复”面试官一眼就能看出你有实战经验。5.2 漏斗分析题核心是分步去重不是简单JOINB站非常重视内容消费转化比如“从曝光到点击再到播放到完播”的漏斗分析是内容运营的日常需求。笔试题里有相当概率出现类似的场景比如“统计每个视频从曝光到点击再到播放的转化率”。这道题的难点在于用户的每一步行为是在不同日志表里的而且在时间维度上有先后顺序。如果你直接用三张表JOIN很容易出现数据膨胀——因为一个用户可能对一个视频曝光了10次、点击了3次、播放了1次JOIN之后可能会出现多对多匹配导致每一步的UV数都被放大。正确的做法是每一步行为单独去重计算UV再在最终结果层做口径统一。也就是说不要求用一条SQL直接得到完整漏斗而是先把曝光UV、点击UV、播放UV分别算清楚再套公式算转化率。笔试中如果能写出“先分步算UV再合并”的思路即使SQL写得不够精简也能拿高分。5.3 累计聚合题窗口函数和自关联的性能差异有一类SQL题长这样“统计每个分区每天截止到当前的累计播放量”。这题的核心是理解累计聚合running total的两种实现方式自关联和窗口函数。很多刚入门的人喜欢用自关联写SELECT a.dt, a.zone_id, SUM(b.play_count) AS cum_play_count FROM zone_daily_play a JOIN zone_daily_play b ON a.zone_id b.zone_id AND b.dt a.dt GROUP BY a.dt, a.zone_id;这个写法能算出结果但性能非常差因为每一天都要把该分区从第一天开始的全部记录关联一遍数据量大时基本跑不出来。实际笔试中如果你写了这种自关联建议在答案后面主动补充一句“如果数据量大可以改用窗口函数优化”并写出窗口函数版本SELECT dt, zone_id, SUM(play_count) OVER (PARTITION BY zone_id ORDER BY dt) AS cum_play_count FROM zone_daily_play;窗口函数版本的执行效率高得多因为数据只需要扫描一遍。这种“性能意识”在真实的数仓开发里极其重要——B站每天处理的数据量很多时候一条SQL写不好任务就要跑几小时影响整个链路的数据产出时效。6. 数仓笔试的主观题与开放题如何答出“项目感”而不是“课本感”笔试的最后通常还有一两道主观题。这类题没有标准答案考察的是你的思维深度和表达能力。但正因为没有标准答案很多同学反而不会答——要么写得太虚全是空话要么写得太窄只盯着一个技术细节猛抠。我想针对这类题目给出一套可参考的思考框架。6.1 开放题怎么答从业务目标倒推设计方案假设题目是“请设计方案支撑B站的内容推荐效果分析”。这类题如果你直接开始写“ODS层同步埋点日志DWD层清洗DWS层聚合……”——就很死板。更好的框架是“业务目标倒推法”。先明确“内容推荐效果”到底要回答哪些业务问题。拆开来看无非这几个推荐位带来了多少曝光点击率如何推荐带来的播放占整体播放的比例是多少推荐场景和关注场景、搜索场景的用户行为差异是什么不同的推荐策略比如不同的召回模型、排序模型效果差异怎么评估一旦把业务问题列出来技术方案就顺理成章了。比如要评估不同推荐策略的效果差异那么DWD层就需要有一张“推荐曝光日志明细表”包含用户ID、推荐位ID、推荐策略ID、曝光内容ID、曝光时间、位置序号等字段如果要看推荐带来的后续行为还要把这批曝光内容ID和后续的点击、播放行为做串联这就涉及到“行为序列日志”的建模。写到这里你不需要再赘述数仓分层了你的方案已经直接落到了表结构设计层面带着强烈的“项目感”。这种答题方式比从头到尾背诵分层架构要高明得多因为阅卷老师能看出来你真的思考过“这个需求到底要什么”。6.2 数据质量问题场景题“数据对不上”的排查思路比答案更重要还有一类开放题可能会换个角度考数据治理比如“报表数据异常运营反馈昨天GMV暴涨你如何排查”。这道题考察的是你的排查思路。我的建议是不要一上来就说“我检查一下SQL有没有写错”而是要建立一个从业务逻辑到数据链路的排查顺序先确认口径是否变化是不是业务方或者自己改了统计口径比如之前只统计支付成功订单现在把待支付订单也算进去了再确认上游数据是否波动是不是某条业务线的数据没有按时同步比如某个渠道的订单表今天重复同步了一条大额订单然后确认调度是否正常是不是昨天的调度任务重跑导致重复写入最后才检查SQL和模型逻辑有没有可能在事实表关联维度时产生了数据膨胀这个顺序背后有一条核心原则先看数据是否可信再看计算是否正确。因为数仓的问题绝大多数不是计算逻辑出错而是输入数据在上游就出了问题。笔试时即便你不能完整答出每一步只要这个排查思路的框架搭对了面试官也会认可你的数据敏感度。6.3 团队协作与跨部门沟通题数仓不是“接需求写SQL”的团队最后还有一类偏软技能的题比如“如果你发现业务方的某个指标口径和数仓维护的口径不一致你会怎么处理”。这种题虽然不考技术但淘汰率却不低因为很多候选人会给出一个幼稚的答案“我直接按他说的改。”真实的处理方式要细致得多。首先是定位口径差异业务方用的是“订单支付成功时间”数仓口径是“订单创建时间”业务方统计的是“去重用户数”数仓看的是“订单量”。差异不搞清楚直接改代码就是埋雷。其次是确认目标和影响范围业务方要这个指标用来干什么如果只是临时看数可以通过临时表解决不一定要改动模型口径如果是长期报表就需要走正式的指标口径变更流程通知所有下游依赖方评估影响。最后是沉淀文档把口径不一致的原因、最终方案、以及影响的报表记录在案。数据口径不一致的问题在成熟的数据团队里是用“指标字典”和“数据字典”来管理的。在笔试中遇到这类题体现出来的是一种“数据团队服务于业务但不能无条件被业务带着走”的专业边界感。能答出这层意思说明你已经有了一定的数据治理意识而不只是一个SQL执行工具。7. 备考B站数仓笔试的实用建议从刷题到能力的三个进阶阶段最后聊一些更落地的备考策略。我知道看到这篇文章的同学很多正处于求职阶段时间紧、任务重很容易陷入盲目刷题的焦虑里。但数据仓库岗位的笔试准备其实是有清晰路径的我把它梳理成三个阶段供大家参考。7.1 第一阶段建立体系化认知而不是背零散知识点很多同学准备面试习惯刷那种“100道数仓面试题”一类的资料背了很多概念比如“什么是事实表”“什么是维度表”“什么是星型模型”。问题在于这些概念是孤立的一旦笔试把它们组合到一个场景里你就不知道怎么用了。我的建议是先花一到两周系统地过一遍《维度建模权威指南》这本书的核心章节以及数仓分层、同步策略、缓慢变化维这几个关键专题。不要求每一个细节都记牢但一定要能在自己脑子里画出一张“知识地图”从业务问题出发到哪里去界定业务过程到哪里选择粒度到设计事实表到设计维表再到数据同步和调度依赖最后到报表呈现和指标解释。这张地图的完整度直接决定了你在笔试中综合题的作答质量。7.2 第二阶段带着场景练手写SQL和建模重点练“取舍判断”第二阶段的重心是练题但练题的方式有讲究。不要只练那种标准答案只有一个的SQL题要刻意练习那些有业务场景、有数据约束的题目。比如自己设定一个场景“一张用户行为表一张用户注册表一张商品订单表请统计每个用户近30天的消费行为并按用户生命周期分群输出。”这种题没有标准答案但你在写的时候需要自己权衡用5天前的用户行为数据还是实时查询用户生命周期分群的标准是什么这个标准在哪里定义如果一个用户没有任何订单行为他在结果里要不要出现这些思考过程比答案本身更接近笔试考察的本质。练的时候可以模拟笔试环境限定时间然后对照自己的答案复盘哪些地方没想周全。7.3 第三阶段围绕B站业务做场景化预判提前准备常用指标口径第三阶段是针对目标公司的定向准备。既然目标是B站建议提前梳理一下B站的核心业务指标做一些场景预判内容生态类DAU、MAU、人均观看时长、视频完播率、互动率点赞/投币/收藏/转发、内容供给量、UP主活跃度商业化类广告收入、会员购GMV、直播打赏流水、大会员新增与续费、广告点击率与转化率留存类次日留存、7日留存、30日留存、流失预警、唤醒率。把这些指标背后的数据来源、统计口径、常用维度想清楚。笔试里遇到相关场景题时你会发现自己几乎不需要现场思考业务问题因为已经提前把数据结构建立起来了。比如问到大会员续费分析你立刻就能想到核心业务过程是“用户开通大会员”和“会员到期”事实表是“会员订单/续费记录”维度是“用户、套餐类型、购买渠道、时间”需要关注的指标是“新购数量、续费率、流失率、客单价”——这套思路一旦成型答题速度和深度都会大幅提升。到这里整套B站数仓方向笔试的核心内容就拆解得差不多了。从我接触过的笔试题目和实际工作感受来看真正能拉开差距的从来不是谁更熟悉SQL函数的写法而是谁能更快把业务问题翻译成数据模型并且考虑到数据链路里那些“不说就会出事故”的细节。希望大家在备考时多带着这个视角去思考问题把自己想象成已经在B站数仓团队工作的人而你手上的笔试卷就是明天要交付给业务方的设计方案。这样练下来考场上自然就稳了。