数据开发笔试复盘:SQL、数据倾斜与数仓建模要点
发布时间:2026/9/1 21:32:48 作者:尧图编辑部 阅读量:1,286

我当年拿到这套“哔哩哔哩2020校园招聘数据开发方向笔试卷二”的时候第一反应是这不就是一份SQL加Java的混合卷吗后来认真刷完才发现数据开发笔试的考察逻辑和普通后端开发完全不同它更看重你对“数据是怎么从业务产生、流转到数仓、最终被分析使用的”这条链路的理解。哪怕已经是好几年前的卷子把它逐题拆开复盘依然能看到如今所有大厂数据开发面试题的母题。这篇文章我想以这套B站笔试卷为切入点按题目背后考察的能力模块来拆解同时把每个模块的备考思路、实战经验和容易翻车的地方一起讲透。无论你是正在准备数据开发校招还是刚转行大数据方向这份复盘都能直接用上。1. 试卷背后的岗位画像B站数据开发到底想要什么样的人1.1 B站业务形态决定了数据开发的技术栈和出题风格先说一个很多人忽略的点B站的数据开发笔试卷和字节、阿里、腾讯的卷子风格差异很大。原因是B站的业务场景有自己的特点——视频内容消费、UP主生态、直播、番剧、游戏这些都是典型的内容社区型业务。内容社区的数据链路和我们熟悉的电商、金融行业不一样。电商数据是强交易属性核心指标是GMV、转化率、客单价内容社区的数据核心是用户时长、互动率、内容供给和消费匹配效率。这就导致B站数据开发的笔试题里必然会出现类似“视频推荐场景下的特征统计”“弹幕和评论的实时热度计算”这类偏内容生态的题目而不会像金融岗位那样考大量风控反欺诈。我当时做完这套卷子的整体感觉是B站不指望你什么都会但要求你具备“把业务问题翻译成数据技术问题”的能力。这份试卷覆盖了四类核心能力SQL功底、大数据组件原理、业务场景建模能力、算法基础。这四个板块其实对应的是数据开发日常工作中的四种真实场景写数仓ETL、调优Spark任务、参与业务指标建设、处理数据倾斜和离线任务优化。1.2 从题型结构反推备考重心虽然没有官方公开的每题分值分布但根据我对同类校招笔试的了解和考试后的复盘试卷结构大致如下题型板块大致题量考察核心备考优先级选择题大数据基础/JVM/计算机网络20道左右基础广度中SQL编程题2到3大题窗口函数、多表关联、复杂查询极高Hive/Spark原理题3到4题执行原理、数据倾斜、优化手段高系统设计/业务场景题1到2题数仓建模、埋点链路、指标口径高算法编程题1到2题数据结构、海量数据处理中学校里的课程通常只教SQL写法和基础的Java/Python语法但企业笔试卷里真正拉开差距的是Hive和Spark的原理理解以及业务场景题能不能答得完整、有层次。我见过太多候选人SQL写得飞快一到“为什么MapReduce会出现数据倾斜”就只说得出“加个随机数”这种结论完全讲不清底层逻辑。这种“知其然不知其所以然”的状态在笔试阶段可能还能蒙混过去到了面试环节就是灾难。2. SQL与Hive看似送分其实是整张试卷的分水岭2.1 窗口函数已经被默认“人人都会”了如果要给B站这类数据开发笔试划一条起跑线那一定是窗口函数。我甚至可以说窗口函数写不顺溜这套卷子的SQL大题基本等于没分。为什么因为数据开发日常工作中排名、去重、累计求和、同比环比这类需求占比极高而它们无一例外都需要窗口函数。典型考法是这样的给一张用户观看记录表字段包括user_id、video_id、watch_time、date然后要求“统计每个用户观看时长最长的前3个视频”。如果不用窗口函数你得写自连接加子查询又长又容易错用row_number()一行搞定select user_id, video_id, watch_time, rn from ( select user_id, video_id, watch_time, row_number() over (partition by user_id order by watch_time desc) as rn from watch_log where dt 2020-08-01 ) t where rn 3;这个答案基本就是标准解法但笔试真正想考察的不是你会不会写row_number而是三个更深的点。第一能否区分row_number()、rank()和dense_rank()。这是每次笔试必踩的坑。row_number()不管有没有并列都按顺序给编号所以名次是1、2、3、4rank()遇到并列会跳号比如两个并列第一下一个就是第三名dense_rank()并列不跳号两个并列第一后下一个还是第二名。涉及排行榜、人数统计这种场景选错函数结果就完全错了。第二partition by后面到底该放哪些字段。这里有个常见错误需要全局排名时忘记去掉partition by或者需要“按天分组统计”却漏了日期字段。我建议拿到题目先画一下“分组维度”和“排序维度”再动手写。第三窗口函数能不能跟where子句一起用——这是最容易暴露基础不扎实的地方。窗口函数是在where和group by之后才执行的所以如果你想筛选“排名前3”的记录不能直接在同一个查询层级里写where rn 3必须包一层子查询。很多人在这一步被扣分就是因为对SQL各子句的执行顺序没有体系化理解。这套卷子里还有一种隐形考点连续问题。比如“统计连续3天登录的用户”。基础解法是用date_sub/date_add配合row_number()通过日期减行号的差值来分组。这类题在B站笔试里出现过相似的变体因为登录行为分析本身是内容社区非常关心的指标。2.2 Hive专项题数据倾斜才是真正的压轴题如果说窗口函数是开胃菜那么数据倾斜就是整个数据开发笔试里最核心的常客。B站的试卷里很少直接问“什么是数据倾斜”而是喜欢用场景题的方式考察比如一个统计视频播放量的SQL任务跑了一个小时还没结束你会怎么排查和处理这类题的本质是考察你对MapReduce/Spark执行机制的理解。数据倾斜的根因一句话就能说清楚数据分布不均匀导致某个reduce task处理的数据量远超其他task整个作业被这个慢节点拖住。常见原因包括key本身分布不均比如某个头部视频的UV远高于其他、空值过多导致所有空值进入同一个reduce、join时小表关联大表的key重复度高。我推荐一个“先定位再解决”的作答框架这在笔试和面试中都很讨喜。第一步看是不是key分布问题用group by或者count一下各个key的数量确认是否存在倾斜第二步看是否由空值引起如果是可以把空值key用随机数打散第三步看是否由join引起小表就做map join大表倾斜就用两阶段聚合。两阶段聚合是笔试的高频标准答案做法是先给key加随机前缀做局部聚合再去掉前缀做全局聚合。我曾用一段伪代码给面试官展示这个思路# 第一阶段加盐局部聚合 select concat(floor(rand() * 100), _, key) as salted_key, count(*) as partial_cnt from data group by concat(floor(rand() * 100), _, key) # 第二阶段去掉盐值全局聚合 select split(salted_key, _)[1] as key, sum(partial_cnt) as total_cnt from stage1_table group by split(salted_key, _)[1]能把这个方案讲清楚已经超过九成的候选人。但如果你想拿高分还需要补充一句两阶段聚合并不是银弹。如果是count(distinct)类的倾斜加盐方案就不好使更合理的方式是改用近似去重算法或者分桶后做局部去重。B站的数据开发笔试里只要你能说出“不是所有倾斜都能用加盐解决”这个认知层次考官就会觉得你有真实项目经验。2.3 刷题之外的硬功夫学会读执行计划关于SQL这块我额外说一个很多人忽略的备考要点B站的笔试卷主观题占比不低部分题目会直接贴一段SQL让你写优化建议。这时候光靠背“用分区、避免select *”这类口诀是不够的你需要能看懂执行计划。Hive的explain命令会告诉你哪个stage是Map端做、哪个stage是Reduce端做join的类型是MapJoin还是CommonJoin有没有出现数据倾斜的风险。我记得这道题当年其实考的就是读执行计划给了一段慢查询让考生根据执行计划找出两个job之间的数据倾斜风险点。我的建议是备考时把explain当成标配技能来练。不只是写对了SQL而是运行一下explain逼自己看一遍执行计划解释每一步在干什么。这样遇到类似的笔试优化题你才能不止答“加一个distribute by”——而是能指出数据从map端到reduce端的分区逻辑在哪里出了问题。3. 大数据组件原理题区分“用过”和“真正懂”的分界线3.1 HDFS与YARN的高频考点非常固定B站这份笔试卷的大数据基础选择题考的范围其实并不偏HDFS、YARN、ZooKeeper都有涉及。但只要不是只背八股愿意往原理深挖一层的人基本都能答对。有意思的是真正拉开差距的不是选择题而是简答题里“描述一条数据从接口上报到最终进入Hive表的完整过程”。这道题表面问的是链路其实考的是HDFS写流程和YARN任务调度。一个及格的回答是数据经由Nginx网关、Kafka消息队列再由Flink或Spark Streaming实时写入HDFS或者通过调度任务批量刷入Hive分区表。但高分回答必须深入到HDFS写入的细节客户端先向NameNode请求上传NameNode返回可用DataNode列表然后客户端将数据分成packet依次写入DataNode同时第一个DataNode会复制给第二个、第三个DataNode形成副本流水线。面试官真正想听的其实是“副本放置策略”和“故障恢复”这两个点因为它们在后续做数据开发时和文件存储设计强相关。B站的视频业务会产生海量小文件如果不懂HDFS的副本机制就理解不了为什么小文件会严重消耗NameNode内存也就给不出“用分区合并、用SequenceFile或ORC格式”这类解决方案。YARN方面的高频考点是容器、资源调度器。笔试里它常以这种形式出现“一个Spark任务提交后资源是怎么申请和分配的”答这个题需要说清AppMaster向ResourceManager注册申请Container然后NodeManager启动Executor的完整流程。能顺手提一句“FIFO调度器会出现队头阻塞Capacity调度器适合多租户资源隔离Fair调度器适合小任务混跑”的基本就是高分答案因为这显示你真的明白生产环境为什么要选Capacity或Fair。3.2 Spark与Flink原理题核心考点不在API而在执行机制B站的数据开发笔试卷中Spark和Flink相关题目占比不低但并不会让你手写复杂的算子链。它更爱考两类问题一类是概念辨析另一类是容错机制。概念辨析最经典的就是Spark的RDD、DataFrame、Dataset三者区别以及宽依赖和窄依赖的区别。窄依赖是指父RDD的每个分区最多被子RDD的一个分区使用比如map、filter宽依赖是指父RDD的每个分区可能被多个子RDD分区使用典型场景是groupByKey、reduceByKey。这个考点跟前面的数据倾斜是连在一起的宽依赖会产生shuffleshuffle是数据倾斜的最常见根源。容错机制方面Spark强调的是血缘关系和checkpointFlink强调的是分布式快照也就是基于Chandy-Lamport算法的checkpoint机制。有一道题我记得特别清楚问“Spark任务计算过程中某个节点挂了是如何恢复的”答案是重新计算丢失的分区但前提是该分区的父依赖还在。想拿高分可以补充一句如果血缘链路特别长重新计算代价很大可以在关键节点加checkpoint切断血缘链。至于Flink如果试卷里出现“如何保证实时计算的Exactly-Once语义”建议从Checkpoint配合两阶段提交来答Kafka作为Source端维护offsetSink端实现预提交和提交两个阶段只有所有算子都完成快照后才会真正提交结果。不一定要求你手动实现精确一次但必须理解这套机制背后的逻辑因为它在实时数据开发中直接决定了数据准确性。3.3 自测一下组件原理能不能讲成一个闭环我在辅导同学准备数据开发笔试时经常用一个自测方法你能不能用一个下午的时间把“一份用户观看日志从产生到变成报表里的DAU”这个过程嘴对嘴地完整讲给一个不懂大数据的朋友听能讲清楚说明你对组件原理的理解已经形成了闭环讲不清楚说明你还在背概念。我见过很多人背熟了“HDFS存数据、YARN跑任务、Spark算数据”但被问一句“这个任务运行时数据是怎么从HDFS到内存再到结果表的”就哑火了。这个闭环需要包括日志采集端通过Flume或Logstash把文件写入KafkaKafka按topic分区存储流式数据实时任务从Kafka消费做ETL后写入HBase或Redis供在线查询同时落一份到HDFS作为离线数据源离线任务通过Hive或Spark读取HDFS上的分区数据加工后写入结果表。整个链路中Kafka是数据管道HDFS是存储底座YARN是资源管理器Spark/Flink是计算引擎。笔试时能把这个闭环图用文字描述出来组件原理题基本就是送分。4. 业务场景与数据建模这类题目答得好基本就锁定offer了4.1 指标口径题先定义清楚再写代码B站这套笔试卷里有一类题让我印象很深它不是考技术而是考业务能力。大意是产品经理给你提了一个需求要统计“视频的完播率”让你给出实现方案。看到这道题的第一反应可能是写SQL但真正被考察的核心是——你如何定义“完播率”。完整回答至少需要延伸到几个子问题完播率的分母是播放次数还是播放用户数分子是播放到百分之百才叫完播还是播放到90%就算遇到倍速播放、拖进度条、重复播放、异常退出怎么处理这些口径不定义清楚SQL写得再漂亮也得返工。这种题在现实中非常常见我称之为“指标口径题”。数据开发的价值百分之八十不在写代码而在跟业务对齐口径。一个清晰的口径应该这样描述统计周期、统计维度、指标定义、事件触发条件、异常排除规则。比如“完播率播放时长达到视频总时长99%及以上的播放次数除以统计周期内的总播放次数排除播放时长小于1秒的无效播放。”这比一上来就写SQL高级得多而且也是笔试评分的重要参考维度。B站的笔试卷会在这个基础上增加场景感UP主上传了一个视频要求统计该视频发布后24小时内的播放完成情况。这里不仅考察口径还考察你对时间窗口和事件时序的理解——事件日志里的播放完成事件能否和视频发布时间精确关联上溢出窗口的数据怎么截断这些都需要在地理位置和时区这类基础条件之外考虑。4.2 埋点日志链路题从上报到入库的完整推演另一类高频业务题是埋点日志链路设计B站特别喜欢考因为B站本身就是强内容平台各种各样的用户行为事件都需要靠埋点来进行数据采集。这类题的基本问法是设计一个用户行为日志系统支持收集用户播放、点赞、投币、评论等行为要求给出数据流转链路和核心表结构。一个可以拿高分的回答思路是这样的首先是事件埋点设计每个事件包含事件ID、用户ID、视频ID、事件时间戳、页面来源、设备信息、扩展参数。然后是传输链路客户端产生事件后先本地缓存批量上报到服务端服务端接入Kafka因为Kafka削峰填谷的能力能够扛住高峰期流量接着数据从Kafka分别流向实时和离线两条链路实时链路用Flink做窗口统计离线链路通过Hive数仓做T1加工。这里有一点很容易被忽略但非常加分小文件问题。如果你在答案里主动提到“实时写入HDFS时要注意控制文件数量避免产生大量小文件”面试官会觉得你确实跑过真实任务。这类问题的细节不需要太复杂但一定要展示出端到端的思维而不是只管某一个环节。4.3 数仓建模维度建模是校招笔试的隐藏高分点还有一个隐藏高分点在很多人的备考中被直接忽略那就是数仓建模。B站一些年份的笔试卷里会有简答题问“如果让你构建一个视频观看数仓你会怎么分层”这其实就是在考维度建模。我的建议是分层的答案可以从ODS、DWD、DWS、ADS四层展开这个业界通用分层就是最稳妥的答案。但你不能只把分层名字写出来要结合具体场景ODS层原样存储埋点日志DWD层清洗和规范化数据将事件日志里的用户ID、视频ID映射到维度表DWS层按天、按视频维度进行汇总形成视频播放量、完播人数等指标宽表ADS层面向业务报表输出最终结果。在维度建模上推荐记一下星型模型和雪花模型的核心区别。笔试如果考到不需要长篇大论能说出“星型模型通过冗余维度字段减少join雪花模型通过规范化维度减少存储但增加查询复杂度”就够了。如果再补充一句“数据开发中绝大多数场景优先选星型模型”说明你已经过了理论阶段有实战判断了。5. 算法与数据结构性价比最高的拿分板块5.1 TopK问题与海量数据处理是数据开发笔试的常客B站的算法题不会特别难考的都是比较经典且贴近大数据场景的题目其中最常出现的就是TopK和海量数据处理。TopK问题我建议准备三种解法。第一种是维护一个大小为K的小顶堆遍历数组遇到比堆顶大的元素就替换并调整堆时间复杂度是O(n log K)第二种是快排partition思路每次把数组分成两部分只对包含TopK的那一侧递归处理平均时间复杂度接近O(n)第三种是针对海量数据的分布式方案将数据分片到多台机器分别求TopK再汇总求全局TopK。为什么这道题会被数据开发笔试看重因为它在真实业务中太常用了。举一个场景每天有上亿条播放事件需要统计播放时长最长的TOP100视频。单机内存装不下自然想到分而治之分完还要合并合并时要维持全局有序——这整个过程和数据开发日常做的分片计算归并汇总逻辑一脉相承。5.2 海量数据去重与概率数据结构是加分项另一类B站笔试喜欢考的算法题是海量数据去重比如“给定上亿个用户ID统计去重后的用户数内存有限怎么做”。标准解法是Bitmap也就是用每一位的0/1来表示一个用户ID是否存在内存占用极低。如果题目里再加一个“误差允许在1%之内”那就要往布隆过滤器方向答了。布隆过滤器是用多个哈希函数映射到一个位数组判断“一定不存在”和“可能存在”两种结论的结构。我建议备考时一定要把布隆过滤器的原理彻底搞懂因为数据开发岗位日常处理UV类指标时经常用到基于近似算法的方案。我在实际参加过的笔试中遇到的版本是要求写“用Java或Python实现一个简单的布隆过滤器核心逻辑”。我当时写的伪代码如下class BloomFilter: def __init__(self, size, hash_count): self.bit_array [0] * size self.hash_count hash_count def add(self, item): for i in range(self.hash_count): index hash(item str(i)) % len(self.bit_array) self.bit_array[index] 1 def might_contain(self, item): for i in range(self.hash_count): index hash(item str(i)) % len(self.bit_array) if self.bit_array[index] 0: return False return True虽然这个实现只用于演示不算工业级但它能清晰展示出“多个哈希函数”“位数组”“允许误判”三个核心特征这就足够拿分了。如果再补充一句“布隆过滤器不支持删除元素如果需要删除可以考虑Counting Bloom Filter”会让阅卷人对你的印象更深。5.3 手写代码之外的边界条件更考验基本功除了数据结构和算法本身B站的笔试算法题还有一个考察重点代码洁癖和边界条件。比如题目要求写出求中位数的代码很多人两个堆的思路都会但一写就容易漏掉“两个堆的元素数量差超过1时需要平衡”这个关键步骤。我个人的建议是备考算法题时一定要在纸上或者在IDE里完整写一遍不要只看思路。B站的在线笔试系统通常不会给你补全提示也没有很方便的调试工具所有细节都要一次写对。尤其是链表相关的题目比如反转链表、判断链表是否有环这类题不涉及高深算法但特别容易在指针移动顺序上出错一错就是编译通过但用例跑不完。刷题数量上我不太建议贪多求全。每天坚持两到三道中等难度的题重点练熟数组、链表、二叉树、HashMap、堆这些核心结构基本就能覆盖大多数数据开发笔试的算法题范围。真正要啃下来的是常见题型的模板比如TopK模板、二分查找模板、链表反转模板这样考场上的思考时间会短很多。6. 考场策略与笔试到面试的衔接会做题也要会“秀”会“聊”6.1 我的做题顺序与时间预算结合B站这套笔试卷的题型构成我建议的答题顺序是先做SQL题再做算法编程题然后做大数据组件原理题最后做业务场景题。理由很简单SQL题和算法题是客观题会就是会不会就是不会先把能拿的分拿到组件原理和业务场景题即使不会也能写一些思路放到后面不影响得分上限。时间分配上假设笔试总时长是120分钟我个人的预算大约如下题型板块时间预算策略选择题20分钟不会的果断跳过不恋战SQL编程题35分钟先审题后建临时表再求解算法编程题30分钟先写暴力解再优化保证有分组件原理题20分钟按点答题优先答核心机制业务场景题15分钟先列口径和框架再补细节这个时间分配的核心思路是难题别贪送分题必须全拿。我看到过太多候选人死磕一道组件原理简答题最后SQL题没时间写那才是真正的因小失大。数据开发笔试的通过率并不高但大多数人的失分点其实都在时间管理和基础题准确率上而不是在那种需要极强创造力的压轴题上。另外一个经验是笔试时把代码写得干净一点哪怕只是变量命名和注释规范一些。很多公司的校招笔试题目不是机器自动判分之后就完事了后续面试官会回看你的答题记录。一份排版整齐、思路清晰的答题记录会在面试官心里的印象分上发挥意想不到的作用尤其是主观题部分。6.2 把笔试卷变成“面试弹药库”我特别想强调一个认知笔试的结束并不是这批题目的终点而是面试准备的起点。B站的面试官在约面时大概率会看到你的笔试成绩和答题详情面试中很可能直接问你“笔试里那道数据倾斜的题你当时是怎么考虑的”如果你笔试时只是草草写了个结论面到这个问题时就很容易接不上。我的做法是每考完一套笔试试卷当天晚上就把所有不会的题目和没把握的知识点整理出来按“题目、考点、错误原因、正确思路”四个字段记录到一份文档里。这样做的好处有两个第一笔试暴露的知识盲区是最高效的复习素材第二把笔试中自己答得好的思路整理成文言化表达面试时可以直接拿来用。比如笔试里那道“如何统计视频完播率”的业务场景题如果你在笔试时从口径、埋点、到DWS汇总三层来答那面试中同样的问题你就可以直接展开成完整的数仓建模思路把笔试时没来得及写的细节全部补上。笔试卷的每一道题本质上都是面试官帮你划的重点一定要把这些重点吃透而不是考完就丢。我在实际备考中还有一个习惯把笔试里出现过的业务场景题全部换成一个跟自己生活相关的场景重新做一遍。比如考了视频完播率我就自己设计一个“统计B站弹幕活跃度”的方案考了TopK我就想一个“统计本周最热门100个搜索词”的完整链路。这种举一反三的练习比单纯刷题更有价值因为它逼着你把知识点内化成解决问题的能力而不是只会背模板。6.3 关于考试环境与细节别在这些地方翻车最后说几个笔试时非常实际的注意事项每一个都是我或身边人踩过的坑。第一提前检查浏览器兼容性和网络环境。在线笔试系统有时候对浏览器有要求比如只支持Chrome或者只支持特定的版本不提前检查进去之后才发现白屏或者代码编辑器加载不出来心态直接崩一半。B站这套卷子当时应该是通过第三方笔试平台开放的登录之后有多长时间、是否允许切屏、是否支持本地IDE这些考试规则都要提前看。第二注意审题尤其是SQL题里“去重”“按照某个字段排序”“求每个类别的前N条”这类关键词。我见过不下五个候选人在“每个用户观看时长最长的前3个视频”里漏掉“每个用户”前两个字的限制写出来的答案没有partition by直接全局排序。这种错误一旦出现整个大题都拿不到分非常可惜。第三如果代码没有跑通不要直接放弃留空。很多笔试平台是按用例通过比例给分的你写出思路并尽量接近正确答案可能也能拿到部分分数。我建议每道编程题即使只写出了暴力解也要提交上去甚至可以在代码注释里简单写一下“这是在内存和时间条件允许下的暴力解后续可以升级为堆优化”让阅卷人看到你的思路层次。从这套B站2020校园招聘数据开发笔试卷来看校招笔试已经过了“考基础知识背题型”就能过关的年代了它越来越像一场开卷的情境模拟让你在一个限时场景里展示自己处理真实数据链路问题的潜质和能力。如果你只把它当成一次考试你就会焦虑如果你把它当成一次和未来的自己对话你就会发现每个考察点背后都藏着这个岗位真正需要的工作方式。