京东2018秋招数据开发工程师笔试题,放在今天看依然是一套很有参考价值的数据开发面试题库。很多准备大数据开发岗位的朋友会问,笔试到底考什么,是不是把SQL刷熟就行。我的看法是,这类题目考察的从来不是单点知识,而是一个数据开发者在真实业务场景里从取数、清洗、统计到排查问题的完整能力链路。这套题虽然已经过去几年了,但考察框架并没有过时,适合准备数据开发、大数据开发岗位面试的同学认真研究,也适合刚入门想了解岗位要求的人用来校准自己的学习方向。
为什么我会专门拿一家公司的笔试题来说事?因为京东的电商业务规模大、链路长,订单、库存、营销、用户行为各种数据交织在一起,这些业务特点直接决定了笔试题里会出现大量“真实世界”的数据处理问题。接下来的内容不会去逐题回忆原题,而是把这类笔试题背后的考点、答题思路和备考方法完整拆给你看。
1. 从业务需求看这套笔试的考察逻辑
1.1 数据开发岗在解决什么问题:先搞懂岗位画像
在聊具体题目之前,先说清楚一个前提。数据开发这个岗位,在2018年和现在的核心职责其实变化不大,都是围绕数据仓库建设、数据管道开发、数据质量保障和业务分析需求落地展开。京东这种级别的电商平台,每天会产生海量的订单、商品、用户行为数据,数据开发要做的事情,就是把分散在各个业务系统的数据统一收集、清洗、加工成可用的模型,再对外提供查询和计算能力。
所以笔试不会只考你“会不会写一段SQL”,而是要看你面对一堆业务命题时,能不能快速抽象成技术方案。比如用户复购率怎么算、订单金额分摊怎么处理、活跃用户口径怎么定义,这些场景题背后考察的是逻辑梳理能力、对数据敏感度的判断,以及处理脏数据时的边界意识。很多刚转行的人容易陷入“背SQL语法”的误区,但真到了笔试现场,会发现题目给的字段总是多几个无关列、日期格式总是不规范,这些都是故意设置的干扰项。
1.2 笔试出题逻辑:一张试卷背后的能力模型
一套好的笔试题目,背后一定贴着岗位的能力模型。数据开发岗的能力模型可以拆成三层:基础编程能力、数据计算能力、工程化意识。基础编程能力对应Java、SQL、数据结构和基础算法;数据计算能力对应Hive、Spark、离线实时链路的设计思维;工程化意识则体现在你对数据倾斜、任务调优、口径一致性等问题的敏感度上。
京东这套笔试题的巧妙之处在于,它并不是简单罗列知识点,而是把这三层能力穿插在题目里。选择题看起来是Java基础,实际上在考察并发和集合的底层理解;SQL题看起来是写统计,实际上在考察窗口函数、多维聚合和性能优化。换句话说,你背书可以过一部分题,但想拿高分,必须真的动手处理过数据。下面我会按照这套能力模型,把几个核心考点逐个拆开讲。
2. 题型结构与高频考点拆解
2.1 Java基础题:集合、并发与JVM的常见陷阱
先说选择题部分。数据开发虽然不是纯后端开发,但Java在大数据生态里的位置基本绕不开,Hive的UDF、Flume拦截器、Spark任务都离不开Java或Scala。所以京东这类公司出Java基础题并不奇怪,考察的基本都是“你实际写过代码吗”的问题。
我印象里这类题目常考的集中在这几类:HashMap和ConcurrentHashMap的结构与线程安全性、ArrayList和LinkedList的适用场景、String、StringBuilder、StringBuffer的区别、JVM内存区域划分和常见的垃圾回收算法。题目难度其实到不了面试题级别,但陷阱很多。比如HashMap在JDK7和JDK8里链表转红黑树的阈值,ConcurrentHashMap在JDK8用CAS加synchronized替代分段锁,这些细节如果你只是背结论,很容易被选项绕进去。
我的建议是,准备这类选择题不要只刷题库,自己打开IDE把源码里的关键方法看一遍,尤其注意初始容量、加载因子、扩容时机,这几个点几乎每年都考。还有一个高频点是异常处理,try-catch-finally的执行顺序、return在finally里的作用,这类题看似基础,但是错误率一直很高。因为很多人只记得finally一定会执行,却忽略了如果finally里也有return,它会覆盖try里的返回值。数据开发的Java题不会太难,但这些细节足以筛选出真正写过代码的人。
2.2 SQL/Hive场景题:数据开发笔试题的重头戏
整套笔试里最核心的部分,通常是几道SQL题,这也是数据开发和大数据开发面试题里最常见的题型。出题方式一般会给你一张订单表、一张用户表、一张商品表,然后要求你计算某个时间窗口内的GMV、复购率、TopN商品等。题目本身不复杂,但非常贴近业务。
考的知识点非常集中:GROUP BY配合聚合函数、CASE WHEN做条件统计、ROW_NUMBER/RANK/DENSE_RANK窗口函数、JOIN时的数据过滤时机、子查询与临时表的性能对比。这些点单独拿出来都不难,但组合到一道业务题里,就非常考验人的建模能力。尤其是同一个指标,用不同SQL写法实现出来的性能可能差出十倍,笔试里通常会通过“你的执行思路是什么”这类追问来考察性能意识。
尤其要注意的是,笔试里常会要求“先写SQL逻辑,再说明在大数据量下如何优化”。这一问才是真正拉开差距的地方。多数人能写出正确SQL,但能讲清楚为什么不能用小表驱动大表、什么时候该用MAP JOIN、数据倾斜怎么预判的人,才是公司想找的。哪怕笔试没有追问,你在SQL旁边加一句优化说明,面试官也会对你另眼相看。
2.3 数据结构与算法题:大数据限定条件下的算法思维
数据开发岗的算法题强度往往不如后端开发,但完全不会考也不现实。京东这套题里涉及的算法题,出题思路更偏“能用在大数据处理里的算法”,而不是纯拼竞赛。换句话说,它考的是你有没有建立大数据场景下的算法思维。
比如常见的TopN问题、海量数据去重、两个大文件求交集、布隆过滤器原理、一致性哈希等。这些题目的共同特点是可以脱离具体框架独立解答,但如果你有Hadoop或Spark的使用经验,会发现它们直接对应着MapReduce的shuffle、distinct、join等底层机制。所以准备算法题时,不要只刷LeetCode高频题,要刻意练习“大数据量限定条件下”的版本。同样是求TopK,数据量小直接排序,数据量大了要想到堆、分治、甚至MapReduce的思路。这种思维转换,正是笔试设计者想看到的。
3. 几道典型题目的实操推演与答题思路
3.1 订单大表统计:从普通SQL到Hive优化的完整推演
我拿一道比较典型的题来做推演:一张订单大表orders,字段有order_id、user_id、sku_id、order_amount、pay_time,假设订单量在亿级。要求统计2024年每个用户的总下单金额和下单次数,并且输出金额最高的前10个用户。
这个需求看起来简单,但写成能扛住大数据的SQL并不容易。先想逻辑:过滤pay_time在2024年,按user_id分组,sum和count,然后排序取前10。普通SQL可以这么写:
SELECT user_id, SUM(order_amount) AS total_amount, COUNT(order_id) AS order_cnt FROM orders WHERE pay_time >= '2024-01-01' AND pay_time < '2025-01-01' GROUP BY user_id ORDER BY total_amount DESC LIMIT 10;这个写法在数据量小的时候没问题,但笔试不会止步于此。如果你面对的是每天几亿条订单数据的Hive表,直接这么写有两个隐患。一个是扫描量太大,全表只有pay_time一个过滤条件,建议在分区表上指定分区字段;另一个是GROUP BY的shuffle压力,相同user_id的数据会集中到同一个Reduce,如果某个用户订单特别多,就可能出现少量Reduce任务数据量严重不均。
所以更完整的回答要补充说明:如果orders表按日期分区,过滤条件应该优化成指定分区范围,避免全表扫描。如果业务上允许,还可以先对子查询做过滤再聚合,减少进入shuffle的数据量。答题时把这两层优化写上,分数会明显不一样。笔试题大多数不会要求你写出真实生产环境的复杂代码,但“正确”和“可扩展”之间差着的这一步,正是数据开发日常工作的真实侧写。
3.2 TopN统计:窗口函数的选型与边界条件
另一类高频题是“取每个分类下销售额前N的商品”。这类需求用窗口函数是最直接的。假设有三张表:商品表sku(sku_id, category_id, sku_name)、订单明细表order_detail(order_id, sku_id, amount)。要求统计每个品类下销售额最大的5个商品。
直接按分类分组后排序是行不通的,因为GROUP BY之后每个分类只剩一行。正确思路是先用JOIN拿到每个商品的销售总额,再用ROW_NUMBER()按category_id分组、按销售额降序编号,最后过滤rn <= 5。
WITH sku_sales AS ( SELECT s.category_id, s.sku_id, SUM(d.amount) AS sales_amount FROM order_detail d JOIN sku s ON d.sku_id = s.sku_id GROUP BY s.category_id, s.sku_id ) SELECT category_id, sku_id, sales_amount FROM ( SELECT category_id, sku_id, sales_amount, ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY sales_amount DESC) AS rn FROM sku_sales ) t WHERE rn <= 5;这里有个容易被忽视的点:相同销售额的并列处理。如果业务上允许并列,应该用RANK()或DENSE_RANK()而不是ROW_NUMBER()。三种窗口函数的差异是笔试常考细节:ROW_NUMBER()顺序编号不考虑并列;RANK()遇到并列会跳过后续编号,比如两个第一名并列,第三名会显示为3;DENSE_RANK()则连续编号,第三名显示为2。答题时主动说明“这里我假设每个商品销售额不同,如果用RANK会更稳妥”,会显得你考虑问题更全面。
除了窗口函数,这个需求还可以用“自连接比较”或“子查询计数”来实现,但性能都会逊色一些。笔试时如果时间充裕,可以简单提一句其他方案的缺陷,这能让面试官看到你对不同技术路线的权衡能力。
3.3 数据倾斜排查:从故障现象到解决思路
数据倾斜几乎是数据开发面试题库里必考题,也是笔试里偶尔以简答题或开放题形式出现的点。所谓数据倾斜,简单理解就是并行计算时大部分数据都集中到了少数几个任务上,导致整体任务卡在长尾。它在笔试里经常不是独立题目,而是挂在SQL题后面的“如果数据量变大,你会怎么优化”这个问题中。
常见原因有几个:一是分组键本身分布不均,比如用户表里“未知用户”或“默认值”占了绝大多数;二是两表JOIN时关联键大量为空或重复;三是单条数据过大,比如一个用户的下单明细量级是别人的几千倍。处理思路通常从三个方向入手:加盐打散、过滤异常键、拆分为两阶段聚合。
我见过一个比较典型的处理案例。某天跑每日汇总任务时,整个作业跑了两个多小时都没结束,查看任务详情发现其中一个Reduce处理了超过60%的数据。排查后确认是JOIN键里有大量空字符串,导致空值全部落到同一个任务。临时解决方案是先过滤空JOIN键,再用随机前缀加盐做二次聚合;长期方案是在上游链路清洗时就把空值默认值提前处理掉。这种问题的排查思路,比背一个处理公式更重要。笔试遇到开放题时,你描述清楚从现象到定位到解决的链路,逻辑完整、分点清晰,就能拿到不错的分数。
3.4 连续登录与留存分析:高频业务题的通用解法
这类题目在大数据开发笔试题里出现频率很高。比如给一张用户登录表login_log(user_id, login_date),要求统计连续登录3天及以上的用户数。这看似是用户运营问题,其实考的是SQL中日期差值的处理,也是数据开发日常报表里最常碰到的需求之一。
思路是这样:先用ROW_NUMBER()按user_id分组、按login_date排序,得到每个用户的登录序号。然后用login_date减去序号对应的天数,得到一个新的日期字段。如果用户是连续登录的,这个日期始终相同;一旦断签,这个日期就会变化。最后按user_id和这个日期字段分组,统计每个分组的数量,过滤掉数量小于3的组。
WITH rn_log AS ( SELECT user_id, login_date, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn FROM login_log ) SELECT DISTINCT user_id FROM ( SELECT user_id, login_date, DATE_SUB(login_date, rn) AS date_group FROM rn_log ) t GROUP BY user_id, date_group HAVING COUNT(*) >= 3;这个思路要理解清楚,因为它可以延伸出很多变体,比如“统计连续活跃N天的用户”“统计连续下单天数超过N天的用户”。核心逻辑都是同一个:用窗口函数生成序号,再用日期减去序号,分组后看数量。一旦掌握了这个套路,笔试里遇到这类题就不会慌。另外这种题在笔试里往往还要求考虑用户一天内多次登录的情况,所以需要使用DISTINCT login_date或按日期去重后再计算,别被重复数据带偏。
4. 针对性的备考方案与实战建议
4.1 数据开发知识点体系:先搭好复习主线
如果你是复习阶段,不要一上来就刷题。先用一张纸把数据开发的知识树画出来:语言基础、SQL/Hive、分布式计算框架、数据仓库理论、常见业务指标、排查调优。每棵树下面再列细节点,比如Hive下面列分区表、分桶表、文件格式、UDF、窗口函数、Common Join与Map Join的区别。
这些知识点之间其实是有依赖关系的。SQL是基础,窗口函数和聚合必须熟练;Hive是基于MapReduce的SQL引擎,理解了MapReduce的shuffle过程,你才能理解为什么某些SQL写法会慢;理解了数据仓库的分层思想,你才能回答“为什么一张明细表要拆成DWD、DWS、ADS”。把这层依赖关系想清楚,复习才有主线,而不是东一榔头西一棒子。我在带人时经常发现,很多候选人背了一堆Hive参数,但问他“为什么Map Join能减少shuffle”就答不上来。这种根上的理解,恰恰是笔试想测的东西。
4.2 刷题路径与模拟安排:按阶段推进效率更高
刷题建议分三个级别推进。第一级是基础SQL题,熟悉GROUP BY、JOIN、子查询、CASE WHEN的常见组合,可以选LeetCode数据库题库或牛客网的SQL题。第二级是业务场景题,自己找真实业务场景练习,比如电商复购率、漏斗转化、留存分析。这些题目不复杂,但非常考口径理解,你在笔试里拿不准的往往不是SQL语法,而是“按什么定义去统计”。第三级是大数据场景题,重点练TopN、去重、中位数、行列转换、连续登录这类“大数据开发笔试题”里的老朋友。
时间安排上,建议把复习周期拉长到一个月以上。前两周完成知识点扫盲加基础题练习,第三周集中做真题和业务场景题,最后一周做模拟笔试,严格控制时间。模拟笔试尤其重要,因为线上笔试和平时在IDE里做题完全是两个环境,你需要在没有代码补全甚至没有编译环境的情况下手写SQL和Java,这种手感必须提前适应。我自己当年就吃过亏,平时写完代码还能靠IDE提示,笔试时键盘敲得飞快但拼错了函数名都发现不了,白丢了不少分。
5. 笔试现场的时间分配与避坑经验
5.1 数据开发笔试失分点:这些坑几乎每年都有人踩
线上笔试容易踩的坑,我按出现频率排个序。第一是审题不细,题目要求“精确到小数点后两位”你没处理,要求“按金额降序、金额相同按时间升序”你只排了金额。第二是SQL语法细节,比如MySQL里limit和排序顺序、Hive里等值连接不支持“!=”,以及日期函数在不同引擎里的差异。第三是Java题忽略默认值,int和Integer的默认值、静态方法能不能访问实例字段,都是选择题里再常见不过的陷阱。
还有一点很多人会忽略,就是答题时的“字段命名”。SQL题如果要求输出某列名,你最好保持一致,比如总额写total_amount而不是amount_total。虽然笔试判卷一般不会严格校验字段名,但清晰、统一的命名习惯,在后面的面试环节会给面试官留下好印象。这个习惯在真实工作中也非常重要,数据仓库里十几张表横跨多个业务方,字段命名是不是规范,直接决定了下游接数的人要不要反复来问你。
5.2 线上笔试环境细节:提前熟悉平台少吃亏
现在的线上笔试基本都在牛客、赛码这类平台上完成,题目提交后会跑测试用例。每个平台对SQL的执行引擎、可用函数、输出格式要求略有差异,提前熟悉目标平台很重要。建议在正式笔试前,用目标平台做一套模拟题,至少确认三件事:是否支持窗口函数、是否要求输出结果集排序、判题是严格比对字段还是看最终结果。
另一个容易被忽略的点是时间分配。一套数据开发笔试题通常包含选择、SQL、编程题和问答题,不同题型分值差别很大。我见过不少同学在选择题上死磕,导致后面的大SQL题草草交卷。正确的做法是先扫一遍全卷,把有把握的大题先拿下,选择题遇到没把握的先标记跳过,最后再回头处理。大题通常分值高且区分度大,先保大分是笔试最实际的原则。时间剩得多的话,再回头啃选择题,哪怕蒙对的概率也高一些。
我个人在实际操作中的体会是,准备这类数据开发面试题,最怕的不是不会,而是知识都见过、但落不到笔头。笔试现场没有搜索引擎,没有同事可问,所有东西都得靠平时的积累和手上的肌肉记忆。如果你把每个考点都当成真实生产问题去思考过一遍,哪怕题目换了个业务背景,你也能快速抓住它的本质。最后再分享一个小建议:笔试结束后,不管考得好不好,把题目和你的答案记下来复盘一遍,过三个月再回头看,你会发现自己对数据开发的理解又上了一个台阶。