3. 数据工程核心技能栈
本章核心目标:建立“技能点→考察逻辑→回答结构”的快速映射,确保面试时每道题都有清晰的表达框架。
数据工程面试中,SQL、Python、大数据框架(Spark / Flink / Hive)是三大必考技能。面试官不会只考语法,而是关注场景理解、性能调优、异常处理。掌握统一回答框架:拆解需求 → 分步实现 → 说出优化点 → 引用项目指标。
三大技能栈面试问答卡片
📌 面试问题:
写一个 SQL 查询,统计每个部门过去 30 天内销售额排名前 3 的员工及销售额。
🎯 面试官考察点
- 窗口函数(RANK / DENSE_RANK)与分区(PARTITION BY)
- 日期过滤与时序数据处理
- SQL 执行计划意识(是否考虑索引/分区剪裁)
🧩 回答框架
- 拆需求:部门内、过去30天、Top3 → 窗口函数 + 日期过滤
- 写框架:子查询 + RANK() OVER(PARTITION BY 部门 ORDER BY 销售额 DESC)
- 加优化:日期列建立索引 / 按月份分区表 / 使用 BETWEEN 避免函数包裹
- 提验证:测试边界(当天数据是否包含、平排名如何处理)
💬 简短示例回答(约80字)
SELECT 部门, 员工, 销售额, rnk
FROM (
SELECT *, RANK() OVER(PARTITION BY 部门 ORDER BY 销售额 DESC) AS rnk
FROM sales
WHERE sale_date >= DATEADD(day, -30, GETDATE())
) t WHERE rnk <= 3;
并补充:为 sale_date 建索引,若表按日期分区还需确认是否实现分区剪裁,避免全表扫描。
🔍 可能追问
- RANK 与 DENSE_RANK 区别?若 Top3 含并列如何处理?
- 如果数据量 10 亿行,如何优化此查询?
- 如何用 Hive Spark SQL 改写?窗口函数在分布式中注意事项?
⚠️ 避坑提醒:不要在 SELECT 条件中对日期列使用函数(如 DATE(列)),会导致索引失效;窗口函数 OVER 内部 ORDER BY 方向写错(DESC/ASC)也是常见低级错误。
📌 面试问题:
用 Pandas 处理一个 10GB 的 CSV 文件,如何避免内存溢出并完成分组聚合?
🎯 面试官考察点
- 大数据场景下 Pandas 的局限性认知
- 分块读取(chunksize)与类型优化(dtype)
- 是否了解 Dask / Modin 等替代方案
🧩 回答框架
- 评估问题:10GB 远超单机内存 → 不能全量读入
- 给出方案:pd.read_csv(chunksize=10000) 迭代处理,每块聚合后合并
- 深度优化:指定 dtype(如 int32/float32),解析日期时用 parse_dates 参数
- 扩展建议:若多次再处理可用 Dask DataFrame 并行计算
💬 简短示例回答(约90字)
chunk_iter = pd.read_csv('file.csv', chunksize=10000, dtype={'col1':'int32'})
result = []
for chunk in chunk_iter:
result.append(chunk.groupby('dept')['sales'].sum())
final = pd.concat(result).groupby(level=0).sum()
同时说明:若列范围小,可使用类别类型(category)进一步压缩内存。
🔍 可能追问
- 如果文件是 GZIP 压缩的,chunksize 如何影响解压?
- Dask DataFrame 底层如何实现分块?与 Pandas 的兼容性?
- 如果需要在每个 chunk 内排序后取 TopN,如何实现?
⚠️ 避坑提醒:不要忘记在最终合并时再次 groupby,因为不同 chunk 可能含相同分组键;chunksize 不宜过大(一般 5k~50k),否则内存不降反升。
📌 面试问题:
在 Spark 中遇到数据倾斜(某个 key 数据量特别大),如何定位原因并解决?
🎯 面试官考察点
- 是否理解 Shuffle 与分区机制
- 倾斜诊断方法(stage 耗时/数据量对比)
- 常见解决方案:加盐/广播/调整分区/自定义分区器
🧩 回答框架
- 定位:看 Spark UI 中某个 stage 长时间运行、task 数据量差距大
- 分析原因:group by / join 时 key 分布不均
- 给出解法:① 加随机前缀(salting)打散大 key ② 小表广播(broadcast join)③ 增大 shuffle 分区数
- 选最优:若倾斜 key 少且大,优先 salting;若表较小,优先广播
💬 简短示例回答(约90字)
// 加盐示例:对倾斜key拼接随机后缀
df.withColumn("new_key",
when(col("key") === "hot_key", concat(col("key"), lit("_"), floor(rand()*10)))
.otherwise(col("key")))
.groupBy("new_key").agg(...)
同时说明:聚合后再将随机前缀去掉,倾斜 key 被分散到 10 个分区,性能提升明显。
🔍 可能追问
- salting 后如何还原结果?对后续 join 是否有影响?
- 如何判断应广播左表还是右表?Spark 3.0 自适应查询如何自动处理?
- 如果倾斜发生在 reduce 端而非 map 端(如 distinct count),怎么处理?
⚠️ 避坑提醒:不要盲目用 repartition(1000) 解决所有问题,要先分析倾斜 key 的分布;salting 时随机后缀范围(如 10~100)要适中,太小仍走同一个 task,太大则小文件增多。
技能点对比速查表
| 技能 | 最高频考点 | 面试官底层意图 | 黄金回答结构 |
|---|---|---|---|
| SQL | 窗口函数、表连接优化、复杂聚合 | 是否具备性能和逻辑拆解意识 | 分步拆需求 + 写伪 SQL + 加索引/分区 + 测边界 |
| Python | Pandas 内存管理、数据倾斜处理、异常捕获 | 是否真的处理过 GB 级数据 | 场景评估 + 分块/类型优化 + 伪代码 + 扩展方案 |
| 大数据框架 | Shuffle 原理、数据倾斜、调优参数 | 是否理解分布式框架核心瓶颈 | 定位(UI)+ 分析原因 + 给出 2-3 种解法 + 选最优 |
💡 面试官解读:不要只背答案,要展示“思考过程”——比如回答 SQL 时先说“我先确认表结构与索引”,回答 Spark 时先说“我先看 Spark UI 中的 task 数据量分布”。这种过程框架比结果更值分。