京东数据开发笔试题解析:SQL、数仓与分布式核心考点
2026/9/7 17:17:25 网站建设 项目流程

2018年京东秋招的数据开发笔试题,我到现在还留着电子版。那年我也投了,虽然没走到最后,但那份卷子前前后后刷了三遍,后来自己也做了几年大数据开发,再去回看,才发现那些考点背后其实就对应着一个数据开发工程师日常要干的活。很多朋友问我现在准备数据开发面试该看什么,我的回答一直是:先把老牌大厂的历年校招笔试题吃透,京东这卷子就很有代表性,SQL、数仓、Hadoop生态、算法都有覆盖,难度适中,非常适合用来查漏补缺。

这篇文章我会从题目考什么、怎么解、有哪些隐藏坑这几个角度去拆,顺便把数据开发笔试里最高频的题型思路讲透。不管你是准备校招还是想转岗数据开发,都可以拿这份内容当复习提纲。我尽量少说废话,直接给你能用的东西。

1. 笔试题背后的能力模型:数据开发工程师到底考什么

1.1 为什么一张2018年的笔试题还值得翻出来看

很多同学有个误区,觉得技术迭代快,2018年的题早就过时了。但数据开发岗位本身不是追新技术的岗位,它的核心是数据仓库设计、离线计算、实时计算、数据质量保障这些东西,底层逻辑非常稳定。哪怕今天我们已经大量使用Spark、Flink,但Hive SQL仍然是离线数仓的主干,MapReduce思想还在,数据倾斜问题也还在。2018年的笔试题考的是这些底层能力,现在依然在考,而且大概率还会继续考。

另外一个原因是,大厂笔试的出题风格一般比较克制,不会出偏题怪题,而是考“能不能干活”的基本功。京东这套题就是典型:SQL占大头,附带了数仓模型、分布式计算原理和少量算法编程。这刚好映射了一个数据开发工程师的真实工作场景——你每天写的ETL就是SQL,你设计的表结构就是数仓建模,你优化的任务就是在跟分布式系统打交道。笔试不是在考你记忆,而是在模拟你能不能接手真实任务。

1.2 数据开发笔试的范围与权重

根据我看到的公开回忆版和后续和几个参加过那场笔试的同学对答案,这套题的题型分布大概是下面这个样子:

考察方向常见题型大概占比考核目标
SQL/Hive窗口函数、多表关联、连续问题、行列转换35%-40%日常取数与ETL能力
数据仓库理论分层设计、事实表维度表、拉链表15%-20%建模能力与业务理解
分布式计算原理MapReduce流程、Shuffle、HDFS读写10%-15%对底层架构的理解
算法/数据结构TopK、排序、哈希、手写代码15%-20%代码基本功与大数据思维
Java/Python基础集合、IO、线程或语法题5%-10%工程落地能力

这个权重分布不只在京东,在多数互联网大厂的数据开发笔试题里基本都成立。如果你现在复习时间不多,按这个顺序分配精力是最稳的。SQL绝对是性价比最高的部分,练好了笔试能过,工作也能直接用上。

1.3 数据开发岗位和其他数据岗的考核差异

我见过不少同学把数据分析师和数据开发工程师的笔试混着准备,结果两边都没抓住。数据分析岗更侧重Excel、Python分析库、AB实验、业务指标设计,对SQL的考察也往往是取数逻辑;而数据开发岗更侧重性能优化、数据准确性、调度依赖、分布式原理。同样是写一段SQL,数据分析师只要查出对的结果就行,数据开发还要考虑数据量大了怎么不跑挂、怎么减少扫描量、怎么避免数据倾斜。

所以在笔试准备上,你不能只会“查数据”,还要知道“怎么存数据”、“怎么高效算数据”。比如同一道分组TopN的题,数据开发岗往往还会追问一句:如果这个表有十亿行,你的SQL会不会OOM?这时候你光写出row_number()是不够的,还得想分区裁剪、谓词下推、Map端聚合这些事。这也是大厂笔试题喜欢设的陷阱——表面考SQL,实际上考工程思维。

2. 高频考点拆解:SQL与Hive的重点题型

2.1 窗口函数:从“分组求TopN”说起

分组求TopN是所有数据开发笔试里最经典的一道题,没有之一。题目通常是:有一个员工表(部门、姓名、薪资),求每个部门薪资最高的前三个人。正解是使用窗口函数:

select 部门, 姓名, 薪资 from ( select 部门, 姓名, 薪资, row_number() over(partition by 部门 order by 薪资 desc) as rn from 员工表 ) t where rn <= 3;

这里容易踩的坑有两个。第一个是row_number()rank()dense_rank()的区别没搞清楚,如果题目要求“薪资相同并列排名,且占用后续名次”,就得用rank();如果要求并列但不超过TopN,就用dense_rank()。很多人背了函数名,却不知道选用场景,笔试时被问“TopN允许并列怎么办”直接懵掉。

第二个坑是把窗口函数放在where里过滤,比如写成where row_number() over(...) <= 3,这在SQL语法里是不允许的,窗口函数只能在select或order by子句中使用。老实说,这个错误我在实际工作里见过不止一次,因为很多人在IDE里写SQL会顺手想这么做。笔试时一道大题里出现这种低级语法错误,印象分会很惨。

除了TopN,窗口函数还需要掌握累计求和(sum() over(order by 日期))、移动平均、分组占比(avg() over(partition by ...))这类场景。这些都是离线数仓开发里非常常用的工具,面试官很容易在笔试题里变着法考。

2.2 连续性问题:连续登录N天怎么算

另一道高频题是“求连续登录N天以上的用户”。比如给定用户登录日期表(uid, login_date),让你求连续3天登录的用户。核心思路很经典:用登录日期减去row_number()的序号,如果连续,差值会相同,再按用户和差值分组计数。

select uid from ( select uid, login_date, date_sub(login_date, row_number() over(partition by uid order by login_date)) as diff from login_log where login_date between '2018-01-01' and '2018-01-31' ) t group by uid, diff having count(*) >= 3;

这道题看起来不难,但有个细节特别容易翻车:用户同一天可能有多条登录记录,如果不去重,row_number()算出来会错。正确做法是先做select distinct uid, login_date,再去算连续。我见过不止一个同学在这上面丢掉全分。

还有更进阶的变体,比如“求每个用户连续登录的最大天数”。思路是在上面基础上,算出每个uid的连续分组diff,然后group by uidmax(cnt)。这种连续问题的本质是“构建与日期无关的分组标识”,理解这个原理之后,不管题目怎么换,你都能把业务场景抽象成同一套解法。

2.3 数据倾斜问题:Hive性能考察点

数据开发笔试里的SQL题有时候不会只让你写代码,还会写一句“表数据量很大,怎么优化”。最常问的就是数据倾斜。所谓数据倾斜,就是某些key的数据量特别大,导致Reduce阶段一个任务处理了99%的数据,其他任务闲等,最后整个任务跑得很慢甚至OOM。

典型场景和解决思路包括:

  • 空值引发的倾斜:比如一堆join key是null,全跑到一个reduce。解法是把空值加上随机后缀,比如concat('null_', rand()),让它们分散到不同reduce。
  • 热点key倾斜:比如双十一当天的某个商品访问量极大。解法是加盐(随机前缀)先聚合一次,然后再去前缀做二次聚合。
  • mapjoin优化:如果一个小表Join一个大表,可以使用mapjoin把大表广播到map端,避免Shuffle。Hive中可以通过set hive.auto.convert.join=true自动优化,但笔试时最好能手写/*+ mapjoin(t) */这个hint。

这种优化题没有标准答案,但考官想听到的其实就是“你知道存在这样一个问题,并且能说出至少一种解决方案”。你如果能在笔试的SQL注释里主动说明“这里考虑到了数据倾斜,我会用mapjoin优化”,会显得你比普通考生高一个段位。

3. 数据仓库与离线计算核心概念题

3.1 数仓分层为什么重要

京东的笔试题里一般会有一道数仓建模题,常见问法是“简述数据仓库的分层结构以及每层的作用”。这题表面简单,但很多人的回答是背出来的,没有理解分层背后的成本权衡。

业界通用分层是ODS(操作数据存储层)、DWD(明细数据层)、DWS(汇总数据层)、ADS(应用数据层)。ODS层基本是原样同步业务库,保持历史状态不修改;DWD层做清洗、规范化、维度退化,把数据变成更易用的明细模型;DWS层按主题做轻度汇总,比如按用户日汇总、按商品日汇总;ADS层直接面向报表和应用,粒度比较粗。

为什么不能把所有逻辑都放在一层做?我自己的体会是:分层是为了控制复杂度和成本。不加分层,所有报表都直接查ODS原始日志,你得在每个SQL里重复处理脏数据、重复join几十张表,开发效率极低,出了问题还不好排查。有了DWD层,脏数据问题在源头解决一次,后面所有人都受益。DWS层把高频汇总指标提前算好,报表查询速度会快很多。虽然分层会增加存储和调度成本,但换来的是研发效率和系统稳定性,这笔账在大厂里算得过来。

3.2 事实表与维度表:如何选择

数仓建模题里另一个必考概念是事实表和维度表。最简单直白的区分:事实表是业务过程产生的“行为记录”,比如订单事实、支付流水,里面主要是可加性的数值度量(金额、数量);维度表是描述业务对象的“属性集合”,比如用户维度、商品维度、时间维度,里面是文本描述和分类。

笔试时经常给一个场景,让你设计订单事实表和商品维度表。这里有一个易错点:商品名称、商品类目属于维度信息,不应该放在订单事实表里,应该通过商品id关联。但在真实数仓开发里,为了查询性能,会在DWD或DWS层做“维度退化”,把常用的商品名称、店铺名直接冗余到事实表里。这种做法违反范式,却符合数仓建模的实践精神。所以面试官问“事实表能不能冗余维度字段”,你不能直接说不能,要能讲清楚什么时候该冗余、什么时候不该冗余。

拉链表也是数仓高频考点。当我们要维护一个不断变化的维度,比如用户的会员等级、收货地址,不能用全量快照(浪费存储),也不能只保留最新状态(丢失历史),这时候就用拉链表。拉链表给每行记录增加start_dateend_date两个字段,表示这条记录的有效期。当数据发生变化时,把旧记录end_date更新为变化前的时间,再插入一条新记录start_date为变化时间,end_date设为未来日期(比如9999-12-31)。

写拉链表的SQL在笔试里最后一道题出现概率很高。核心逻辑是:用增量数据关联历史全量数据,找出哪些字段发生变化,把变化的旧记录关闭,新记录插入。很多人的解答能做到这一步,但容易忽略“如果一天内同一用户状态变了多次怎么处理”这个问题。实际生产里,我们一般只会拿当天最新快照去更新,不会处理一天内的多次变化,因为业务方通常不关心这个粒度。如果题目没说清楚,尽量在答案里补充一句假设,能体现你的思考深度。

3.3 Hadoop生态原理题:MapReduce与HDFS

数据开发笔试里会出一些基础原理题,比如MapReduce的详细执行流程、HDFS写文件的流程。这类题占分不算太多,但是如果你答得不好,容易让面试官质疑你的基本功。

MapReduce执行流程的记忆可以分四个阶段:Map阶段、Shuffle阶段、Reduce阶段。Map阶段从HDFS读取数据,按行解析成key-value,执行map逻辑,输出中间结果。Shuffle阶段细分为分区、排序、溢写、合并、拉取、归并排序几个小步骤,中间数据的key会按分区器分发到对应的reduce任务,同时按key排序。Reduce阶段拿到所有中间结果后,再对每个key调用reduce函数,输出结果写入HDFS。

很多人容易把Shuffle理解成“从map传到reduce”的简单过程,但实际它有复杂的磁盘IO和网络传输。笔试如果让你设计一个优化方案,第一反应可以是从源头减少Shuffle数据量,比如使用combiner进行map端合并,或者调整mapreduce.job.reduces来控制reduce数量。

HDFS写流程也是经典题。客户端向NameNode发起写请求,NameNode检查权限和路径后返回可以写入的DataNode列表,客户端按块(默认128MB)将数据分包发送到第一个DataNode,第一个DataNode再复制给第二个,第二个复制给第三个,然后逐级返回ack,最后客户端关闭流,写操作完成。这里的关键点是“流水线复制”和“收到所有ack才认为写入成功”,这保证了数据的多副本一致性。

我自己的建议是不要死记硬背,你可以把HDFS想象成一个快递仓库:NameNode是库管员,只记录每个包裹放在哪个货架,DataNode是货架本身。客户端存东西时先问库管员,库管员分配几个货架,客户端依次把货放进第一个货架,第一个货架再复制到第二个,这样即使一个货架塌了,东西还在。有了这个画面,面试时描述细节就不容易卡壳。

4. 算法与数据结构在笔试中的出题方式

4.1 手写排序:快排和堆排是常客

数据开发笔试的代码题不会只有SQL,还会有一两道编程题,往往让手写经典排序、链表反转、TopK这类。尤其在时间限制下,很多人掉进“用库函数”的坑里——用Collections.sort()确实能过题,但面试官问一句“排序原理是什么”就哑火了。

快速排序算是最高频的考察点,因为它和分布式里的“分治”思想一致。手写快排的关键在于partition函数的稳定性,需要把小于基准值的放左边,大于基准值的放右边,然后递归。这里注意别把边界处理错,我建议用双指针写法,不容易越界。

private int partition(int[] arr, int left, int right) { int pivot = arr[right]; int i = left; for (int j = left; j < right; j++) { if (arr[j] < pivot) { swap(arr, i++, j); } } swap(arr, i, right); return i; }

堆排序在数据开发里同样重要,因为TopK问题最典型的解法就是维护一个大小为K的小顶堆或大顶堆。笔试手写堆排序对很多人来说有点难度,但至少要把adjustHeap写对,或者能够用Java的PriorityQueue完成TopK:

PriorityQueue<Integer> heap = new PriorityQueue<>(k); for (int v : nums) { if (heap.size() < k) { heap.add(v); } else if (v > heap.peek()) { heap.poll(); heap.add(v); } }

求最大的K个数用小顶堆,堆顶是堆中最小元素,当新元素比堆顶大时替换。这个思路比全量排序空间复杂度低非常多,特别适合“海量数据求TopK”这种场景。

4.2 海量数据经典题:100GB文件求高频词

这类题是笔试的“压轴大题”,也是数据开发岗区别于后端岗的独特题目。题目通常长这样:给定一个100GB的文件,每一行是一个字符串,求出现次数最多的100个词,机器可用内存只有2GB。

正确的解法分三步走:哈希分片、统计、合并。第一步用hash(word) % M把大文件拆分成M个小文件,这里的M要保证每个小文件能加载进内存,比如拆成200个,每个500MB,2GB内存可以装下。第二步对每个小文件单独用HashMap统计词频,得到每个小文件内部Top100。第三步将每个小文件Top100汇总到一起,用一个包含词频的堆或者MapReduce思想做全局Top100。

这道题考察的是你对“分治法”的理解,和MapReduce是同一个思路。很多人答到最后只想到用堆,却忽略了分片,这样在2GB内存限制下直接就OOM了。还有人在回答里说用字典树(Trie树),虽然也是方案,但相对复杂,面试官不一定喜欢,最稳妥的普适答案还是hash分片+堆。

如果题目进一步问“怎么保证相同词一定分到同一文件”,答案是hash函数有确定性,相同字符串的hash值相同,取模结果也一定相同。这是一个低概率出错但重要的细节,最好在答案里主动讲出来,证明你理解原理而不是背答案。

4.3 布隆过滤器:面试官想听你说出“允许误判”

除了海量TopK,布隆过滤器也是数据开发方向的高频概念题,通常结合“如何快速判断一个URL是否已经被爬取过”或者“如何判断用户ID是否存在”来问。

布隆过滤器是一个很节省空间的概率型数据结构,通过多个哈希函数把元素映射到一个二进制位数组中。查询时如果任意一个哈希位置的bit为0,则一定不存在;如果都为1,则可能存在,有一定误判率。

笔试答题时的加分点是主动说明它有两个特性:有误判率、不能删除元素。不能删除的原因是一个bit位可能被多个元素共享,置0会影响其他元素。通常解法是使用计数布隆过滤器,但会增加存储开销。如果你能把“为什么不能删除”讲清楚,面试官会觉得你真的理解数据结构的本质,而不是简单背概念。

5. 编程题与工程能力的考察

5.1 语言基础:Java/Python/Scala怎么选

笔试时编程题一般支持多语言,但建议用自己最熟的。数据开发岗在Java和Python之外还会用Scala,校招笔试里用Scala的人比较少,如果是Spark方向可能会给Scala题。不过我更建议在笔试时用Java或Python,因为阅卷人更熟悉,出错的概率也小。

Java里高频考察点是集合类、HashMap的原理、多线程和IO。比如HashMap的put流程、扩容机制、为什么并发环境下不安全。Python里一般是列表字典的用法、推导式、装饰器这类。Data开发岗的笔试不会考特别偏的语法,但会结合场景,比如写一个脚本从日志中提取特定字段并统计频率。

这里有个实用经验:写Python统计词频,千万避免在循环里用count()这种O(n²)写法,数据量一大根本跑不动。正确思路是用collections.Counter或者手动字典计数:

from collections import Counter counter = Counter() with open('data.txt') as f: for line in f: word = line.strip() counter[word] += 1

虽然很简单,但很多同学会写错,比如在with缩进上栽跟头。笔试环境不会给提示,缩进错了就是编译错误。

5.2 从手写代码到工程思维:任务幂等与重跑

实话讲,数据开发工程师日常很少手写排序算法,更多是在写ETL任务和调优SQL。那笔试为什么还要考编程题?因为它想看到你写代码的条理和边界意识,这直接影响你在生产环境里的代码质量。

比如笔试如果你写一个函数,要考虑到输入为空会怎样,数据量特别大会怎样,异常的日志怎么打。如果能主动写出“空值处理”、“异常捕获”,这个代码的水平就上了一个档次。

更高级的考察方式是让你设计一个离线任务流。比如给定业务数据,需要每天凌晨从RDS全量同步到HDFS,然后做清洗,再产出报表,你会怎么设计调度?这题的要点是保证任务可重跑、数据不重复。我们一般会在ODS层加分区,以当天日期作为分区,如果任务失败重跑,直接覆盖当天分区,不产生重复数据。同时在DWD层计算时,对上游分区做确认,如果上游数据未就绪,则等待重试。

工程思维的另一个关键是“幂等”。一个任务重复跑两次,结果应该一致。离线任务通常通过insert overwrite table ... partition(dt='2024-01-01')保证幂等;实时任务则更复杂,需要利用唯一键去重。笔试题里如果涉及输出方案,主动提“保证幂等”绝对是加分项。

5.3 Shell及常用的数据开发工具

笔试偶尔会有一两道Linux/Shell题,比如查找大文件、统计日志行数、crontab设置。很多人忽略这部分,但数据开发不可能不开服务器,会写简单的Shell能体现落地能力。

高频命令包括:grepawksedsortuniq -chead/tail。比如统计日志中每个IP出现次数,一条命令就是:

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10

这里容易出错的点是uniq只能合并连续的重复行,所以必须先sortuniq。这道题几乎每年都有人栽,就是因为调换了顺序。如果你能在笔试里把这个命令解释清楚,再顺手写一个等价Python脚本,会让阅卷人觉得你基础扎实。

6. 面试准备避坑指南与经验心得

6.1 我当年踩过的坑

我第一次做这套题时,SQL部分写了很长,结果跑都没跑。后来复盘发现问题出在“只写不测”上。笔试时编辑器没有运行环境,你写出来的SQL全靠脑子编译,但逻辑哪里有问题很难发现。所以现在我给所有准备笔试的同学一个建议:平时练习一定要在本地装个MySQL或者用Hive/Spark环境,把每道题亲手跑一遍,尤其是窗口函数和连续问题,不跑一遍你根本不知道坑在哪。

另一个坑是“背题不挖原理”。比如我背过MapReduce流程和HDFS写流程,但面试官追问“为什么edits文件要放在NameNode本地磁盘?”,我一愣。笔试答对是第一步,你要准备把每个答案延伸出三个“为什么”。这些年我自己做面试官时,最反感的就是候选人答得像百科词条,一问细节就卡住。

还有一个坑是时间分配。笔试题量不小,有单选、多选、SQL大题、编程题。我当年在单选辨析题上花了很多时间,导致后面的大编程题时间不够,只写完大概框架。后来学聪明了,拿到卷子先花两分钟看完整体分值,优先保证SQL大题的完成度,因为一道SQL题的分值通常超过好几道选择题。笔试时间短,策略比蛮力更重要。

6.2 常见问题速查表

高频问题核心思路常见踩坑
分组TopN窗口函数row_number/rank/dense_rank过滤窗口函数时未包一层子查询
连续登录日期减去行号构建分组键忘记去重、同一天多条记录
数据倾斜空值加随机后缀、热点key加盐、mapjoin只想到调参数,不提具体场景
数仓分层每层职责明确,控制复杂度说不清每层典型表
拉链表开始日期+结束日期不处理一天多次变化
海量数据TopKhash分片+堆没提内存限制对分片数的影响
布隆过滤器多hash到位数组忘了说误判率和不能删除
Shell统计词频sort后再uniq无脑用uniq导致结果错误

这张表里的内容是整个数据开发笔试的核心骨架,建议你在复习时对着表格逐一自测,能不看答案把每行完整讲清楚,再去刷题效果会好很多。

6.3 最后一件事:别忽略“讲思路”的能力

虽然这是笔试题,不是面试题,但有些大厂的在线笔试会有一道“只要写文字”的题目,让你描述方案。比如“请设计一个日活用户统计方案”,或“某个SQL跑了3小时还没出结果,排查思路是什么”。这类题没有标准答案,但能看出你的思路是不是完整的。

我自己习惯用“分情况讨论”的方法来答。先问清楚统计口径:日活是按登录去重,还是按设备去重?再提数据来源:从业务库同步还是从埋点日志算?然后说技术选型:离线用Hive/Spark,实时用Flink?最后补充异常处理:如果上游数据晚到怎么办,如果数据对不上怎么排查。这四块一展开,即使细节不完美,整体也已经是一套合格的工程方案。

最后再给大家一个非常实际的建议:准备笔试前,一定要建立一个自己的本地练习环境。不一定要很强的服务器,装个Docker,里面起个MySQL或者Hive,把你在牛客和历年真题里遇到的SQL题都跑一遍。我之前帮人改题,最大的感受是很多人不是不懂解法,而是语法细节错误太多,比如字段别名不写as、group by漏字段、left join写成交叉join,这些在真实环境一执行立刻暴露。笔试没有试错机会,所以平时多跑,形成肌肉记忆,才是稳的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询