news 2026/8/29 11:35:15

货拉拉大数据中心笔试题复盘:SQL与数仓建模的实战要点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
货拉拉大数据中心笔试题复盘:SQL与数仓建模的实战要点

“货拉拉2018秋招大数据中心笔试题”——单看这个标题,可能觉得是一份过期真题,没什么参考价值。但我在准备秋招时正好卡在那个时间节点,这份笔试给我的冲击相当大。它没有堆砌偏题怪题,而是把Hadoop、Spark、数据仓库建模和实际物流业务绑在一起,考察的是“你能不能直接用数据解决业务问题”。后来我入职做了一段时间大数据开发,再回头看这份题,才明白当年很多答案其实只答到了表面。这篇文章会把题目按类拆开,结合出题意图和我的踩坑复盘,给准备大数据岗位面试的朋友一份能落地的参考。

我不可能把每道题原封不动背下来,毕竟过去几年了。但当时考完和几个同学对了答案,也和一位参与出题的面试官做过交流,还原出来的题型结构和核心考点是可信的。如果你是准备校招或跳槽的数据岗候选人,这篇复盘值得完整看一遍。

1. 一份物流大数据笔试的“考察地图”:货拉拉想招什么样的人

1.1 笔试环节在整个秋招流程里的定位

秋招笔试不是用来筛天才的,它最大的作用是快速排除“简历很漂亮但基本功不扎实”的人。货拉拉大数据中心2018年那场笔试,时长90分钟,题量不算大,但覆盖面非常宽:选择题考基础概念,编程题里既有SQL也有算法,最后还有一道数据仓库建模的开放题。如果你只看岗位JD,会以为重点在Spark、Hive这些组件,实际上试卷里大量题目都在考察“能否把业务问题翻译成技术方案”。这个定位非常重要,决定了你复习的时候不能死啃底层源码,也不能只刷LeetCode。

我当时犯过一个错误:临考前一周还在猛刷MapReduce shuffle阶段的源码细节,结果试卷上只在选择题里带了一道关于shuffle的简单判断题,真正的分数大头是SQL和建模分析。笔试的目的不是考倒你,而是看你在有限时间内能不能稳定输出常用技能,所以它的题目往往偏重通用性和方法论,而不是刁钻冷门。

1.2 大数据中心的技术栈与考察范围推测

从题目内容可以反推货拉拉大数据中心当时的技术栈:Hadoop生态是绝对主角,HDFS、MapReduce、Hive、Spark都有涉及,流计算考了Kafka和Spark Streaming的简单概念,没有出现Flink。数据仓库部分考察了维度建模和分层设计,这和当时多数互联网公司数仓团队的要求一致。由于货拉拉是货运物流平台,订单派单、司机履约、用户行为这些数据天然带有空间和时间属性,所以SQL题里出现了“按城市统计”“司机活跃区间”等场景。

从岗位要求来看,他们希望候选人具备三种能力:第一,扎实的工程基础,包括数据结构、Java或Scala编程;第二,大数据组件的基本使用与原理理解,至少要知道数据倾斜怎么处理;第三,数据建模和业务分析能力,能理解核心指标的定义和口径。这三点基本就是那场笔试考察地图的三大板块,下面的复盘也按这个逻辑展开。

1.3 业务场景驱动的出题逻辑

货拉拉的主营业务是同城货运撮合,业务角色包括用户端、司机端和平台运营。2018年正是补贴大战火热的时候,增长、完单、留存是三个最核心的分析方向。笔试出题人很聪明,把业务抽象成了几道纯技术题,例如“统计每个城市近30天完单量Top100的司机”,看起来是SQL题,背后其实是城市维度下的TopN分析;而“求用户连续N天下单的最大天数”,其实在考察留存和活跃的分析基础。

这种出题逻辑对候选人有很强引导性:你不需要了解货拉拉的商业模式,但必须具备把“业务问题转化为数据计算逻辑”的能力。我后来在真实工作中发现,这恰恰是大数据工程师日常做得最多的事。笔试里那道建模题,直接给出了用户、司机、订单三张业务表,要求设计数仓DWD和DWS层的表结构,实际上就是面试官在日常工作中的简化缩影。

2. 基础编程题复盘:SQL和数据结构的必拿分项

2.1 经典SQL题:司机完单量TopN与连续参与时长统计

笔试中有一道SQL题我印象很深:给一张司机订单表,包含司机ID、城市、订单创建时间、完单时间、订单状态,要求统计每个城市在2018年8月完单量排名前100的司机及其完单量。这个题就是经典的分组TopN,核心写法是用窗口函数。我当时的答案类似下面这样:

SELECT city, driver_id, order_cnt, rk FROM ( SELECT city, driver_id, COUNT(*) AS order_cnt, ROW_NUMBER() OVER(PARTITION BY city ORDER BY COUNT(*) DESC) AS rk FROM driver_order WHERE order_status = 'finished' AND finish_time >= '2018-08-01' AND finish_time < '2018-09-01' GROUP BY city, driver_id ) t WHERE rk <= 100;

这道题不难,但有两个隐藏坑。第一是订单状态过滤,如果算错把未支付订单也算进去,结果会偏大;第二是从表字段里提取月份的写法,如果用substr会有性能问题,而且容易忽略时间字段类型,最稳妥的做法是直接使用时间范围条件,这样还能利用分区裁剪。

连续变量题考的是“司机连续N天有完单记录的最大天数”,比如判断每个司机在8月最长的连续出勤天数。经典做法是用排名减日期法:按司机分区按日期排序得到rank,用日期减去rank得到一个伪日期,相同伪日期就是连续的。大致SQL如下:

SELECT driver_id, MAX(consecutive_days) AS max_consecutive_days FROM ( SELECT driver_id, dt, DATE_SUB(dt, rn) AS grp FROM ( SELECT driver_id, dt, ROW_NUMBER() OVER(PARTITION BY driver_id ORDER BY dt) AS rn FROM ( SELECT DISTINCT driver_id, dt FROM driver_order WHERE order_status = 'finished' ) t1 ) t2 ) t3 GROUP BY driver_id, grp;

这里一定要先对不同日期的完单做去重,否则同一人同一天多单会被当成多天,导致连续天数虚高。当年我就在这个细节上翻过车,最后统计出来的结果和实际业务对不上。

2.2 高频数据结构题:TopK与滑动窗口的变形

笔试算法部分没有为难人,考了经典的海量数据TopK和一道滑动窗口变体。TopK题要求从一亿个整数里找出最大的100个数,限制内存。标准思路是用大小为100的最小堆,先填充100个元素,然后每个新数如果大于堆顶就替换再调整堆,复杂度O(N log K)。Java里直接用PriorityQueue实现,简单可靠。

这道题很多人能说出思路,但手写时出bug的地方在于:堆里存的是最大值还是最小值,堆顶是什么意思,如何初始化。我见过同学把最小堆写成最大堆,结果取出来的前100个是“刚好最小的第100个以后的数”,完全反了。这里要理解,维护一个最小堆,堆顶是当前Top100里最小的数,如果新数大于堆顶,说明这个新数有资格进入Top100,同时要踢掉当前Top100里最小的那个数,也就是堆顶。

滑动窗口那道变体是:给定一个整数数组和窗口大小k,输出每个窗口最大值。这题最优解是用双端队列,队列里存下标,保证队首永远是当前窗口最大值的下标。核心代码不复杂,但边界条件很容易漏,尤其当窗口滑动时,队首下标已经小于当前窗口左边界时要弹出。这道题在LeetCode上是Hard难度,实际上思路理顺后就是几行代码。笔试时我用了暴力法,嵌套循环,数据量小能过,但面试官后来告诉我,他们更想看到O(N)的解法。

2.3 基础题作答的防坑细节

基础编程题最怕的不是不会,而是“会但做错”。我总结了几个笔试时常见的丢分点:

  • SQL里能写窗口函数就不要用自连接,写错了性能差,阅卷人也会觉得你不够熟练;
  • 算法题先确认输入规模和数据范围再选方案,不要一上来就写堆排序;
  • 手写SQL必须注意字段类型和NULL值处理,COUNT(字段)会自动跳过NULL,COUNT(*)不会;
  • 时间不够时,优先把思路写出来,再补代码,阅卷一般会看关键逻辑给分。

这类的确不是高端技术,但在笔试场景里,它们就是你和别人拉开差距的地方。基础题是整个试卷的“必拿分项”,因为后续大数据组件和建模题更开放,分数有波动,如果基础题都丢分,大概率会被淘汰。

3. 大数据组件与架构题:从原理到实战的血泪教训

3.1 Hadoop与Spark原理题背后的考察点

选择题里考了MapReduce的shuffle过程、Spark的宽窄依赖、RDD血缘关系、Kafka的消费者组机制。这些知识点都是大数据开发面试的常客,但货拉拉这套题有个特点:它不会直接问“shuffle分为哪几个阶段”,而是给一个场景,问你“这个操作会产生几个stage”或者“下面哪个操作会引起shuffle”。这意味着你需要理解原理,而不是背概念。

比如有一道题问:Spark中groupByKey和reduceByKey的区别,哪个更好?表面上是考两个算子,实际面试官想考察你是否理解Map端合并(combine)对数据量的影响。reduceByKey在map端先做一次聚合,能大幅减少shuffle数据量,而groupByKey直接把所有原始键值对发到下游。在写代码时,能用reduceByKey的地方尽量不要用groupByKey。我当时把区别和性能影响写完后,又补了一句“如果key分布特别不均匀,reduceByKey也可能遇到数据倾斜”,这算加分项,因为这道题其实在暗示数据倾斜的概念。

HDFS原理题考了副本放置策略:第一个副本放在客户端所在节点,第二个副本放在不同机架的节点,第三个副本放在与第二个相同机架的不同节点。这个问题看起来是死概念,但出题人加问了一句“为什么第二个副本要放在不同机架”,这就牵扯到机架故障容灾和带宽权衡。答到“防止整个机架故障导致数据丢失”还不够,最好补一句“机架间数据传输会消耗带宽,所以第三个副本选择同机架不同节点来平衡可靠性与性能”。

3.2 数据倾斜问题的完整解答路径

数据倾斜是大数据笔试和面试里最常出的场景题,货拉拉这套题也不例外。题目给了一个Spark作业:统计司机订单量,按司机ID聚合,但部分大司机订单量极大,导致某个reduce任务运行特别慢,让你给出解决方案。我当时写了好几条,现在复盘下来可以整理成一套完整解答:

第一,定位倾斜。通过Spark UI查看某个stage里任务的输入数据量差异,如果某个任务输入远大于其他任务,基本可以确认发生了数据倾斜。笔试不需要你写UI细节,但提到“先在UI趋势中看任务耗时和输入数据量”会让阅卷人觉得你有实战经验。

第二,加盐随机前缀解决。这是最常见的方法,思路是把key加上随机前缀打散,再分两步聚合。具体到“按司机ID聚合订单量”这个场景,可以先给每个司机ID加上一个0到n的随机数,做一次聚合,然后去掉前缀再做二次聚合。这个方案能解决数据倾斜,但要注意随机前缀的基数n要足够大,否则还是可能斜。代价是数据量膨胀n倍。

第三,过滤异常key。有些倾斜不是业务正常产生的,而是爬虫或脏数据导致的,比如某个null值或空字符串占据了大量数据。如果倾斜key是这种无意义值,最好的办法不是加盐,而是直接过滤掉。当时我就想到过滤null,还专门写了一句“需要和业务确认空值是否有统计价值”。

第四,使用Broadcast Join替代Reduce Join。如果一个大表和一个小表join时出现倾斜,可以把小表广播到每个executor,避免shuffle。用Spark写就是broadcast(hashTag)。这种办法对维表join特别有效,比如订单表join城市维表,直接把城市维表广播出去,并行度立即提升。

我把这些方案都写上去之后,又加了一句“要根据倾斜key的性质选择不同方案,而不是盲目加盐”,这大概是我笔试里写得最像“有经验的人”的一句话。

3.3 架构设计题:百万级订单实时与离线链路怎么画

这套笔试题有一道大题是画架构图,用的是文字描述加箭头:假设货拉拉每天有百万级订单,需要设计一条离线分析链路和一条实时监控链路,数据源是MySQL业务库和埋点日志,目标是为BI报表和实时大屏提供数据。

这道题考察的是全局架构视野。我当时用了经典Lambda架构思路:实时链路和离线链路分开,最终在服务层合并。

离线链路大概画成:业务库和日志 -> Canal采集MySQL binlog -> 落入HDFS -> 用Hive/Spark进行ETL -> 数仓分层(ODS/DWD/DWS/ADS)-> 同步到MySQL/ClickHouse -> BI报表。

实时链路:业务库binlog或日志 -> Kafka -> Spark Streaming/Structured Streaming -> 实时计算指标 -> 写入Redis/ES -> 大屏接口读取。

要明确画出数据分层,并且解释每一层的作用。其实面试官更关心你对“离线实时一体化”的理解,所以不能只画两条平行线,要在最后说明“离线任务是小时级或T+1,实时任务是秒级,两者在DWS层的指标定义必须一致”,这就是从经验出发拔高回答。

关于工具选型,我当时写的是Spark Streaming,因为在2018年Flink还没有像现在这么流行。如果你现在回答这道题,完全可以直接说Flink。但要注意,笔试要看时代背景,不是越新越好,而是你是否能理解实时计算的核心是“事件时间、窗口、水位线、状态管理”这些概念,而不是套一个框架名词。

4. 数据仓库建模题:物流场景下最难啃的骨头

4.1 从“货拉拉”业务出发,维度和事实怎么选

笔试最后一道开放题是:给出用户表、司机表、订单表、支付表,要求设计数仓分层并给出DWD和DWS层的表结构。这道题没有唯一标准答案,但特别能看出候选人有没有真实建模经验。我当年答得中规中矩,后来工作做了几张数仓模型,才体会到当时漏掉了多少细节。

先说维度怎么选。订单表作为核心事实表,维度至少包括用户维度、司机维度、城市维度、时间维度、订单状态维度。这几个维度缺一不可。用户和司机要区分开,因为货拉拉的平台里二者是不同角色,但本质上都是“人”,简历里很多新人会犯的错误就是只建一张用户维表,没想清楚司机和用户其实有各自特殊属性,比如司机有车型、常驻城市、认证类型,用户有企业或个人标签,这些属性在建维表时要区分。

事实表的选择要看业务粒度。订单事实表明确为“每笔订单一行”,这是最细粒度。对于支付信息,如果一笔订单可能有多个支付事件(部分付款、退款),支付可以单独建模成累积快照事实表,而不是简单地把金额字段塞进订单表。

至于分层,我写的结构是:

  • ODS层:原始日志和业务表,原样同步,不加清洗。
  • DWD层:对ODS做清洗转换,统一字段格式,比如把订单时间拆成日期和小时,把城市ID关联到城市名称,清理无效数据。
  • DWS层:按主题汇总,比如“司机每日完单汇总表”“城市每日交易汇总表”。
  • ADS层:面向具体报表应用,比如“运营团队看的城市日报”。

这个分层方案在所有互联网公司都类似,但笔试题里要写出“为什么这样分层”。我当时的理由有三个:隔离原始数据减少重复清洗;明确定义中间层让下游指标口径一致;权限和血缘更清晰。

4.2 拉链表和累积快照事实表在订单场景的应用

笔试的附加题里有一个小问,问如何保存司机星级和常驻城市的历史变化。这个问题现在看就是典型的拉链表场景。我当时只写了“加生效时间和失效时间两个字段”,但没解释怎么查询历史某个时间点的状态。现在把完整思路记录下来。

拉链表的核心是,在DWD层建一张维度表,包含driver_id, star_level, city_id, start_date, end_date, is_active。每天用业务库里最新的数据与昨天全量做对比,新增和变化的记录插入新版本,同时更新旧版本的失效时间。查询时用WHERE start_date <= '2018-08-20' AND end_date > '2018-08-20'就能取到当时状态。这种设计在数据量较大、变化频率较低的场景下非常划算。

累积快照事实表用来跟踪一个流程的多个状态变化时间。比如订单从创建、支付、司机接单、完成到取消,每个状态都有一个时间字段,事实表一行就是一笔订单,包含order_create_time、pay_time、accept_time、finish_time、cancel_time。这样在计算“从下单到完单平均耗时”时就不用join多张表,直接在同一条记录里做时间差。笔试里订单和支付如果分开建模,最后还是要回到订单事实表做累积,所以我在支付表设计里写了这个思路,阅卷人应该能看出我理解状态流转。

这里有一个很容易被忽略的点:状态时间字段允许NULL。比如一笔订单还没支付,那么支付时间就为空。在写加工SQL时必须用MAX(if(condition, time, null))这类写法把状态时间填到对应列,不能用简单的聚合把这个字段丢掉。

4.3 指标口径不统一的坑

建模题还有一个陷阱:一张汇总表里,不同部门对“完单量”有不同定义。运营觉得司机点击“完成订单”就算完单,财务觉得收到用户支付才算完单,数据分析组可能又要求排除异常订单。笔试题目没有明说,但在一个“城市每日订单汇总表”的字段设计里,我写了“order_cnt”字段,后面有人问这个口径是什么,我就懵了。

一个合理的设计是:在DWS层就把业务口径固化成多个字段,例如order_finish_count(司机操作完成口径)、order_paid_count(用户支付口径)、order_valid_count(去掉取消和异常后的口径)。每个字段都加注释说明口径来源。这样做的好处是下游直接用字段名就能对齐口径,不需要反复解释。如果只建一个order_cnt,后面必然会出现不同部门取数结果不一样,然后再回来吵架。

这道题给我的启发是,数据建模不光是建表,还要建立“指标字典”。笔试虽然不会让你写完整的字典,但你可以在字段注释里体现这种意识。我当时写表结构时,每个关键字段都加了comment,这应该是加分项。

5. 复盘与长期建议:笔试之后,成长才刚刚开始

5.1 站在出题人角度反推复习重点

复盘这份笔试题,我最大的感受是:出题人不是在考“你背了多少知识点”,而是在考“你有没有做过真实项目”。因为真实项目的核心不是会调API,而是知道什么时候用Hive、什么时候用Spark SQL、为什么离线用分区分桶、实时为什么选Kafka和Flink。这套题里的SQL题和建模题,基本上就是大数据开发日常工作的简化版。

如果准备类似的大数据中心笔试,建议从三个方向准备:

第一,SQL必须练到条件反射。分组TopN、连续问题、留存计算、窗口函数、行转列这些题型要多练。推荐直接用LeetCode数据库题,和笔试难度差不多。

第二,大数据组件原理不能只停留在“用过”。至少要能回答出Spark作业提交流程、宽窄依赖、shuffle机制、HDFS读写流程、Hive的元数据存储、Kafka的ISR机制。不用背源码,但要能画图讲清楚。

第三,数仓建模需要动手设计一次。不要只看书,可以找一个你熟悉的业务,比如外卖、电商、打车,自己定义业务过程和维度,建一套完整的数仓分层表。面试官一旦问你建模细节,你会发现设计一套表远比想象中复杂。

5.2 关于货拉拉这份笔试,我还想说几句

很多人觉得2018年的笔试已经过时,不值得看。但恰恰是这种“不追赶新技术”的题目,反而最能看出基础能力。Spark Streaming那题虽然现在大家都用Flink,但背后的实时流处理思想没有变。数据倾斜问题更是直到今天都是高频面试题。再看建模题,只要有数据团队,就会需要理解维度和事实的人。

从我个人经验来说,笔试完之后一定要做一件事:把所有错题和卡壳题整理成一个“错题本”,并且给每道题补充“出题人想考什么”和“真实工作里什么时候会遇到”。比如我整理数据倾斜时,就联想到一次线上任务跑了几小时没跑完,最后用加盐和过滤空值解决的问题,两者一对应,知识就牢固了。

最后分享一个我自己验证过的方法:做笔试题时,如果时间允许,尽量把你的思考过程写在题目旁边。比如SQL题,我会在写代码前先写一句“先按城市分组,再按完单数排序取前100”。笔试不是机器阅卷时,这些思路能帮阅卷人理解你的逻辑,即使代码有小错,也可能给你过程分。更重要的是,这个习惯一直沿用到我现在的工作中,每次写复杂逻辑前先写注释,回头维护代码时会感激当年的自己。

如果你正在准备大数据岗位,希望这份复盘能帮你在笔试环节少踩几个坑。题目本身会变,但基础能力、建模思维和业务理解永远是核心,把这些练扎实,不管哪一年的真题,都不会难倒你。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 11:34:26

Hermes Agent 5分钟搭好性能监控,不再盲猜

Hermes Agent 5分钟搭好性能监控&#xff0c;不再盲猜 【免费下载链接】hermes-agent The agent that grows with you 项目地址: https://gitcode.com/GitHub_Trending/he/hermes-agent 凌晨两点&#xff0c;用户反馈 Agent 响应变慢。你翻日志&#xff0c;只有几行报错…

作者头像 李华
网站建设 2026/8/29 11:30:50

写文献综述怎么选AI?我从通用大模型聊到毕业之家

又到开题季&#xff0c;很多同学最头疼的不是“写不出来”&#xff0c;而是&#xff1a; 文献读了几十篇&#xff0c;还是串不成研究脉络&#xff1b;AI 给的参考文献看起来像模像样&#xff0c;一查作者、年份、期刊全是编的&#xff1b;生成内容像“文献流水账”&#xff0c;…

作者头像 李华
网站建设 2026/8/29 11:30:43

集群高峰下先守住解析链路

集群高峰下先守住解析链路高并发场景下保障 Kubernetes 集群的稳定性&#xff0c;关键在于精准定位并巩固基础设施层与内核层面的关键瓶颈点。 排查高并发下的解析超时时&#xff0c;先区分业务 Pod、DNS 服务和节点网络三层指标。业务扩容并不会自动消除 DNS 查询放大、连接池…

作者头像 李华
网站建设 2026/8/29 11:25:11

Dograh快速入门:从Docker Compose到第一个AI电话助手的完整教程

Dograh快速入门&#xff1a;从Docker Compose到第一个AI电话助手的完整教程 【免费下载链接】dograh Open source voice AI platform. Self-hosted alternative to Vapi and Retell. On Prem, BYOK across Speech to Speech or LLM/STT/TTS, with a visual workflow builder, M…

作者头像 李华
网站建设 2026/8/29 11:25:10

数模国赛元胞自动机实战:从MATLAB实现到经典模型解析

1. 项目概述&#xff1a;从零到一&#xff0c;构建你的数模国赛元胞自动机工具箱如果你正在为数学建模国赛&#xff08;MCM/ICM&#xff09;做准备&#xff0c;并且看到了“元胞自动机”这个听起来有点玄乎的词&#xff0c;心里正犯嘀咕&#xff1a;这玩意儿到底是个啥&#xf…

作者头像 李华
网站建设 2026/8/29 11:25:08

大模型跨领域知识融合:本地部署与RAG工程实践

这次我们来看一个偏“判断”层面的 AI 话题&#xff0c;但它完全可以落到工程层面来验证&#xff1a;AI 无边界融合多领域知识。 Dario 在公开讨论中多次强调一个判断——AI 的能力正在脱离单一领域的限制&#xff0c;同一个模型体系可以同时处理编程、数学、法律、医学、创意…

作者头像 李华