尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

唯品会数据开发岗秋招面试复盘:SQL、数仓与实时计算全解析

唯品会数据开发岗秋招面试复盘:SQL、数仓与实时计算全解析 这些年秋招季我经常会翻到一些旧笔记恰好整理到了当时参加唯品会2019秋招数据开发岗的完整复盘。那会儿数据开发这个岗位还没有现在这么“卷”但考察的深度和方向已经非常明确SQL是基本功离线数仓是主线实时计算是加分项。如果你正准备投递数据开发岗或者正在纠结怎么准备大厂数据岗面试这篇文章基本能帮你把考察重点、面试套路和实战避坑一次性理清。我先把结论放在前面唯品会数据开发岗的考察风格属于典型的“电商大厂通用型”——不考偏题怪题但特别重视你对数据仓库建模的理解、对Hive/Spark等离线计算引擎的掌握深度以及能不能把业务问题翻译成技术方案。笔试会卡一轮SQL和算法技术面会深挖项目里的数仓分层、数据倾斜、指标一致性这些细节。下面我按时间线把整个流程拆开讲。1. 岗位画像与考察节奏先搞清楚他们要什么样的人1.1 数据开发岗在电商大厂到底做什么投简历之前我建议你先想明白一件事数据开发岗和数据分析岗、大数据平台开发岗是有本质区别的。很多同学投递时容易混淆结果面试时答非所问。从唯品会这类电商公司的组织架构来看数据开发岗的核心职责可以概括为三块离线数仓建设负责从业务库、日志、第三方渠道把数据同步到数仓然后完成ODS、DWD、DWS、ADS各层级的建模、清洗、加工最终产出供BI报表、数据分析师、算法团队使用的数据表。数据服务与保障保证数据任务按时产出、数据质量可靠包括调度系统的维护、任务血缘管理、数据对账、异常监控告警。实时计算开发随着业务对时效性的要求提高数据开发岗需要承担一部分实时链路建设比如Flink/Spark Streaming消费Kafka做实时大屏、实时特征、实时报表。也就是说你不仅要会写SQL还要懂调度、懂存储、懂引擎原理甚至要懂一点业务指标口径。面试官考察的就是你“能不能独立把一个数据需求从取数到建模再到上线跑通”。1.2 2019秋招的考察节奏与环节分布我当年的整个流程是这样的网申投递、在线笔试、技术一面、技术二面、HR面Offer审批。不同批次可能略有差异但整体结构差异不大。这里说一下笔试环节的通过率感受。数据开发岗的笔试会同时考到四类内容计算机基础数据结构、Java/Python基础、操作系统、网络、SQL编程题、大数据组件原理、少量数仓建模设计题。其中SQL题占比最高大概能到40%左右其次是大数据组件Hadoop/Hive/Spark原理约30%剩下的是算法编程和计算机基础。所以如果你准备时间有限优先攻克SQL和Hive/Spark原理这两块决定了你笔试能不能过线。2. 笔试真题复盘SQL和数仓基础是最大分水岭2.1 高频SQL题型窗口函数是必拿分项唯品会笔试里的SQL题难度中等偏上考的不是简单select而是实际业务中高频使用的分析场景。我复盘下来最常出现的题型有以下几类每一类我都会附上核心解法和示例。第一类分组TopN问题比如“统计每个品类下销量最高的前3个商品”。这类题的核心就是row_number() over(partition by ... order by ...)然后再套一层子查询把rn过滤出来。当年考的一道题大概是这样的-- 表结构orders(order_id, product_id, category_id, sales_amount) -- 需求统计每个品类下销售额排名前3的商品 SELECT category_id, product_id, sales_amount FROM ( SELECT category_id, product_id, sales_amount, ROW_NUMBER() OVER(PARTITION BY category_id ORDER BY sales_amount DESC) AS rn FROM orders ) t WHERE t.rn 3;这里有个细节值得注意如果业务上存在销售额并列的情况用ROW_NUMBER还是RANK要取决于需求。ROW_NUMBER是唯一递增编号同分也会分出先后RANK同分会重复排名且后续排名会跳跃DENSE_RANK同分重复但后续排名不跳跃。面试官很可能会追问这个问题你得能说清楚三者的差别和适用场景。第二类连续登录问题比如“找出连续登录3天及以上的用户”。标准的解法是使用lag或lead窗口函数或者用date_sub(login_date, rn)构造连续分组。-- 表结构user_login(user_id, login_date) -- 思路登录日期减去行号若日期是连续的差值相同 SELECT user_id FROM ( SELECT user_id, login_date, DATE_SUB(login_date, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY login_date)) AS grp FROM user_login ) t GROUP BY user_id, grp HAVING COUNT(*) 3;这道题的变形很多比如“连续7天”“连续30天”“连续活跃用户数”解法套路都一样但需要你理解为什么date_sub之后分组能保持连续。这个原理如果说不清楚面试官会怀疑你是背题。第三类留存率与复购率计算这类题非常贴近电商业务。比如“计算每日新增用户的次日留存率”。核心是自关联或者left join按用户首次活跃日期分组SELECT t1.first_date, COUNT(DISTINCT t1.user_id) AS new_users, COUNT(DISTINCT t2.user_id) AS retention_users, COUNT(DISTINCT t2.user_id) / COUNT(DISTINCT t1.user_id) AS retention_rate FROM ( SELECT user_id, MIN(login_date) AS first_date FROM user_act GROUP BY user_id ) t1 LEFT JOIN user_act t2 ON t1.user_id t2.user_id AND t2.login_date DATE_ADD(t1.first_date, 1) GROUP BY t1.first_date;这种题在笔试里不是让你真去跑而是考察你的逻辑是否清晰先找新增再找次日有回访的用户最后算比率。做题时注意两个坑一是分母要去重二是LEFT JOIN避免把新增用户过滤掉。2.2 数仓建模设计题星型模型、雪花模型与拉链表除了SQL笔试还会出现简答/设计题常见场景是“请为一个电商平台设计订单事实表和商品维度表并说明模型选型理由”。这一块我当时的回答思路可以给你参考选星型模型还是雪花模型核心看维度的规范化和查询性能的平衡。星型模型维度表冗余、层次扁平适合OLAP查询SQL写起来简单join次数少雪花模型维度表做了规范化拆分消除冗余但增加了join层级。互联网数仓里星型模型更主流因为查询性能和易用性优先。事实表设计要区分事务事实表和周期快照事实表。订单累计快照、每日库存快照用周期快照表交易流水、点击日志用事务事实表。拉链表是一个非常高频的考点用于记录维度属性随时间的变化。比如用户等级、商品价格如果直接覆盖更新就丢失历史于是设计start_date和end_date两个字段配合daily分区表做全量比对更新。笔试里会让你设计表结构和更新逻辑你要能写出“开链、关链、新增”三步SQL。当时笔试还考了一道很有意思的题给定一份用户订单明细统计“每个用户首次下单到第二次下单的平均间隔天数”。这题其实就是lead窗口函数取下一次下单时间再datediff计算间隔最后取均值。这类题看起来复杂拆解后就是窗口函数聚合很考察基本功。2.3 算法编程题以LeetCode中等难度为主数据开发岗的算法题不会像后端开发那样出hard难题但中等难度的题目还是需要准备的。我当时碰到的是“给定一个无序数组求最长连续序列的长度”核心思路是去重后用HashSet从每个连续序列的起点开始遍历时间复杂度O(n)。def longestConsecutive(nums): nums set(nums) max_len 0 for num in nums: if num - 1 not in nums: cur num length 1 while cur 1 in nums: cur 1 length 1 max_len max(max_len, length) return max_len刷题建议以LeetCode Top100里涉及数组、哈希表、字符串、链表的题目为主排序和双指针也要熟。笔试平台一般是牛客网模式上可能不是leetcode那种核心代码模式而是需要自己处理输入输出这点提前练一练省得考场上手忙脚乱。3. 技术面核心环节离线链路与实时计算考察实录3.1 Hive必问点存储格式、分区分桶、UDF通过笔试之后我进入了一面这轮主要考察的是大数据基础功底。面试官从Hive开始问起层层递进。他先问“你用过哪些Hive文件存储格式分别有什么优缺点”这个问题看似基础但能把两者区别讲清楚的人其实不多。我的回答思路是TextFile是默认的纯文本格式可读性好但压缩率和查询性能都很差Parquet是列式存储按列压缩在查询只需要部分列时能大幅减少IOORC也是列式存储在Hive生态里压缩比和查询性能通常更好但Parquet在Spark生态中的兼容性更通用。所以具体选型要看技术栈——如果公司以Hive为主ORC很常见如果以Spark为主Parquet更稳妥。接着他抛出一个非常典型的业务问题“一张订单表每天几千万条查询某个用户最近10笔订单很慢怎么优化”这题考察的就是分区和分桶。我的回答分三步第一按日期做分区裁剪查询时限定最近一个月分区把扫描数据量降下来第二如果经常按user_id查询可以对user_id做分桶让同一个用户的数据落在同一个桶内查询时直接定位到桶第三在桶内字段上建排序结合bucket pruning进一步提升效率。然后面试官又追问了UDF的开发流程。UDF分三类UDF一对一、UDAF多对一聚合函数、UDTF一对多行转列。我当时手写过身份证号解析的UDF就顺带介绍了继承UDF类、重写evaluate方法、打包上传、create temporary function注册的完整过程。3.2 Spark考察重点宽窄依赖、shuffle调优、内存模型Hive之后自然而然地进入Spark。面试官问的第一个问题很有代表性“Spark宽依赖和窄依赖的区别以及为什么窄依赖可以流水线执行”我当时的回答窄依赖是指父RDD每个分区最多被子RDD的一个分区使用比如map、filter、union子RDD可以直接在父RDD分区上原地计算无需shuffle宽依赖是指父RDD每个分区可能被子RDD的多个分区使用典型是groupByKey、reduceByKey、join父分区的数据需要跨节点重新分发也就是shuffle。shuffle要落盘、要网络传输是Spark作业性能瓶颈的根源所以优化shuffle是Spark调优的核心目标。紧接着他问“你线上Spark任务遇到过数据倾斜吗怎么定位和解决的”这是我强烈建议重点准备的题因为几乎必考。我复盘了一个真实案例现象是跑一个订单维度的聚合任务其他executor几十秒跑完某个executor跑了半小时最后OOM。定位思路是先看Spark UI上的Stage耗时再通过查看每个task处理的数据量发现某个task的输入数据量是其他task的几十倍基本确认key分布严重不均。解决方案我说了三个过滤脏数据如果倾斜的key是空值或无明显业务意义的数据比如空字符串、未知ID可以单独过滤或加随机前缀后再打散处理加随机前缀两阶段聚合对倾斜key先加随机数前缀进行第一轮局部聚合再去掉前缀做第二轮全局聚合。适用于聚合类操作对join类问题无效广播小表如果大表join小表时出现倾斜可以map端广播小表避免shuffle。然后他让我背一下Spark on YARN的资源分配参数和内存模型。这部分如果没实际调优过很容易慌我列一下参数和含义spark.executor.memory控制executor堆内内存spark.executor.memoryOverhead控制堆外内存默认是堆内存的10%用于JVM本身、字符串常量池、网络缓冲等spark.executor.cores控制executor的CPU核数spark.executor.instances控制executor数量。内存模型上Spark 1.6之后引入了统一内存管理堆内分为Storage内存、Execution内存和保留区域Storage和Execution可以互相借用避免出现一边空间浪费一边GC频繁的问题。3.3 Flink与实时计算Time、Watermark、Exactly-Once二面的时候面试官突然切到了实时计算。他问的是“你用过Flink吗简单讲讲Flink和Spark Streaming的区别。”这题很考察认知广度。我的回答是Spark Streaming是基于微批的准实时计算把流数据切成一个个小批次处理吞吐量高但延迟在秒级典型延迟在几百毫秒到秒级Flink是真正的流式计算引擎事件逐条处理延迟可以做到毫秒级并且支持基于事件时间(event time)的窗口计算天然契合对乱序数据有要求的场景。另外Flink在状态管理、精确一次语义(Exactly-Once)方面做得更彻底。然后他追问Watermark的作用。我用了一个通俗的类比来解释Watermark是“我等多长时间就不再等了”的标记。比如事件时间是12:00的窗口允许乱序5秒钟那么当Watermark推进到12:00:05时就触发计算12:00那个窗口的结果。如果一条迟到数据在Watermark之后才到达就只能被丢弃或进入侧输出流。实际项目中要结合业务容忍度来设置乱序时间太短会导致结果不准太长会延迟出结果。那轮面试快结束时他问我“你们实时任务怎么保证数据不丢不重”我说我们用的Kafka Flink方案Kafka的offset由Flink checkpoint机制管理开启exactly-once模式后Flink会把状态和offset一起做快照发生故障时从最近一次checkpoint恢复配合Kafka consumer事务性写入可以做到端到端精确一次。不过这需要上下游都支持事务或幂等写入否则只能做到至少一次(at-least-once)下游需要做去重。3.4 手写SQL环节从数据倾斜到指标设计二面里还有个手写SQL环节面试官在白板上出了几道题。其中最让我印象深刻的一道是“统计连续7天有购买行为的用户且这7天每天的购买金额都大于100元”。这道题把连续性问题条件过滤窗口函数结合在了一起。我的解法思路是先用where过滤掉金额≤100的记录再按用户分组用date_sub(login_date, row_number())构造连续组最后having count(*) 7。关键在于“先过滤再算连续”如果先算连续再过滤逻辑就完全错了。另一个手写题是“计算某品类商品的GMV周同比”要求考虑节假日调整。这个题目本质上在考察数据分析思维周同比是指本周累计GMV相对上周同期的变化但遇到春节、双11这类大促周期简单周同比会失真应该用活动周期对齐再比较。面试官借此考察你是不是只懂技术、不懂业务这个表达很重要。4. 面试中的高频追问与答题思路4.1 “讲一下你简历里这个项目”的正确打开方式技术面一定会让你介绍项目。我踩过很大的一个坑是第一次面试时把项目描述得像流水账——先做了什么后做了什么最后实现了什么。面试官根本不感兴趣。后来我总结了一套“项目讲述公式”业务背景放在第一句用一句话说清楚这个项目解决了什么问题然后是技术架构用三到五句话说明数据从哪来、经过哪些环节、最后落到哪里接着是你具体负责的模块要精确到表怎么设计、任务怎么写、参数怎么调最后留一个钩子主动抛出你在项目中遇到的一个难题和解决过程引导面试官往你熟悉的方向问。以我当时做的“用户行为分析数仓”项目为例我会这样讲业务背景是App端每日产生大量埋点日志业务方需要按小时维度查看用户转化漏斗但原有流程是日志落HDFS后第二天跑批时效性不够。所以我在ODS层直接对接Kafka实时接入DWD层做清洗和session划分DWS层做小时级聚合再通过预聚合结果供前端大屏查询。项目中最棘手的问题是session划分时存在大量超长session我用“间隔30分钟无操作则切分”的策略处理并用Hive/Spark优化了session划分任务的数据倾斜。这样一讲面试官会主动问你session划分的细节和倾斜优化正好踩在你的准备范围内。4.2 数据质量与指标一致性大厂面试的隐藏考点这类问题不会直接问“你怎么保障数据质量”而是会通过场景题出现比如“运营反馈昨天报表的GMV和财务部对不上你怎么排查”“你的数仓里订单金额字段有的表叫order_amount有的表叫pay_amount怎么统一”“凌晨3点调度任务失败了第二天早上才发现怎么避免”我的回答思路通常包含四个层面数据质量校验在任务里加入数据量波动监控比如昨日分区行数相比前日波动超过20%则任务报警关键指标设置阈值校验比如订单金额不为负。指标口径登记建立指标字典每个指标必须有统一定义。比如“GMV”指用户支付成功的订单金额包含退款但在统计周期内尚未退款的订单而“实付金额”是扣除退款后的净额。这些口径一定要在需求评审阶段对齐并在代码注释和元数据系统里登记。对账机制核心报表每天与业务库进行对账Kafka实时链路会有实时与离线数据交叉比对如果实时结果与离线结果偏差超过阈值立即触发告警。链路监控用调度平台自带的任务依赖和告警功能设置任务失败自动重跑和电话/短信告警配合数据质量平台做表级和字段级血缘追踪。4.3 大厂面试的软技能业务理解与沟通表达最后想提醒一点数据开发岗不是纯技术岗。面试官非常看重你能不能听懂业务方说什么。这轮面试里有个问题是“如果商品运营想分析‘高价值用户’的购买偏好你怎么定义高价值用户”如果只回答“根据消费金额排序取前20%”那只是及格水平。更好的回答是先问清楚高价值用户是看近30天消费金额、消费频次、还是用户生命周期价值(LTV)不同业务目标下定义完全不同。先确认口径再谈实现这本身就是数据开发的基本工作方式。5. 秋招投递与面试节奏的实操建议5.1 简历怎么写能更匹配数据开发岗简历这块我给出三个具体建议。第一项目经历中一定要有明确的“数量级”——比如“处理日均5亿条日志数据”“数仓共2000张表”“调度任务3000个”面试官对数字非常敏感没有数量级描述会让人觉得项目是玩具项目。第二技术栈要写出“熟练、掌握、了解”的边界不要全部写成精通。面试官如果发现你写了“精通Spark”却又答不出shuffle原理反而会扣分。第三把“业务结果”写进简历比如“通过口径统一将报表差错率从5%降到0.5%”——这种描述能有效区分你和其他候选人。5.2 时间线管理提前批、正式批与内推渠道当时我投递的是秋招提前批这类批次的优势是流程快、竞争相对小部分公司提前批不通过还能转正式批。建议你重点关注几个时间节点7月到8月是提前批开放期9月到10月是正式批集中笔试期。内推不是必须的但有内推可以让简历优先被看到避免简历石沉大海。找内推的渠道一般是牛客网、公众号、学长学姐、以及各大技术社区的内推帖注意别为了内推泄露个人敏感信息。5.3 心态调整与多线面试的经验秋招最崩溃的不是某一场面试挂了而是连续一周每天都有笔试面试时间根本排不开。我的做法是每周固定半天完整刷题其余碎片时间只看牛客网的面经和错题把每一轮的面试题目及时复盘记到备忘录里避免同一类问题在下一场面试里再卡壳为了应对不同公司的流程冲突可以礼貌地和HR沟通调整面试时间绝大多数公司都能协调。说实话我当时也在很多公司面试时遇到过答不上来的题。回头来看面试官有时候并不是想等你一个完美答案而是在看你怎么思考、怎么沟通、怎么在不会的情况下给出合理的分析路径。数据开发岗尤甚——这个岗位每天面对的是脏数据、延迟任务、口径争议解决问题的思路比答案本身更重要。你如果能把这个态度表现出来面试就已经成功了一大半。5.4 关于Offer选择的个人体会最后再多说一句当年我纠结很久的事数据开发岗最后拿到几个Offer时怎么选。除了看薪资我更建议你关注三件事第一团队使用的技术栈是否足够主流如果还在用纯MapReduce写数仓那你的成长速度会受影响第二数仓建设是否已经有完整规范还是处于“人肉取数加工厂”阶段这决定了你进去后是写代码还是写临时SQL第三实时链路是否已经落地如果有机会在生产环境接触Flink对你后续的职业发展加成会很明显。数据开发这个岗位门槛不高但天花板很高。笔试面试只是第一关真正拉开差距的是你进入岗位后能不能从“会写SQL”升级到“会设计数仓”再到“能推动数据规范和数据质量建设”的人。这个成长路径比秋招本身更值得提前想清楚。
返回列表