好多人的简历在技术栈方面写得那叫一个五花八门,瞅着好像啥都会。然而面试官随便抛出个基础问题,立马就原形毕露了。近期有个哥们儿去面试医药供应链数仓岗位,其简历上写着Flink、Doris、Spark全家桶,结果却被一道题给问得愣住了,紧接着就直接被淘汰了。
面试官询问DWS层究竟是怎样进行聚合的,这位仁兄仅仅会背诵ODS、DWD、DWS、DIM层的定义。如此一类回答一听便知是背题的结果,根本不存在任何实际项目方面的经验。数仓分层的关键核心目的在于实现解耦、达成复用以及降低成本,而并非是让你单纯去背诵名词。
于医药供应链接项目里头,DWD层级需进行明细拉宽操作,将订单主表同明细表予以关联。把脏数据予以清洗,对字段规范加以统一之后,使最细粒度的明细数据得以落地。待至DWS层级的时候,要依据门店以及药品这两个核心维度来开展轻度汇总。
特别是意味着落至地面的单独店铺在单个日子里的药品售卖情况进行汇总的表格。如此这般,当更高层级的商业智能报表需要以周或者月为单位的销售数据之际,直接去查询详细汇总了相关数据存储区域层的汇总数据便可以了。并非每次都得去扫描几十亿条明细数据,查询的速度能够提升至原来的10倍以上,并且还能够避免重复实施计算,进而节省集群所需要的资源。

面试官紧接着问了关于维度建模的问题,这一位回答星型模型跟雪花模型的区别的时候,又仅仅只会照着书本背诵,在实际项目里选择星型模型存在三个关键原因,全部是基于实际操作经验。
首先是查询性能占据优先位置。星型模型呈现为事实表直接对维度表进行关联 ,不存在多个层级的维度彼此关联的情况,如此一来就能够减少数量众多的表join操作。在面对大数据量的状况下,其查询速度相较于雪花模型要远远更快。其次是开发维护所需要的成本更低。雪花模型将维度拆解成为多个层级,这就在开发以及排查问题的时候需要对多层表进行关联操作,然而星型模型它的结构是更为清晰的,即便是数仓领域的新人也能够较快加以掌握。
首先,第三点是要适配大数据引擎的特性,Hive、Spark、Doris这些引擎,它们针对大表多表join的优化能力,比起关系型数据库而言,差得很远。之后,雪花模型的多层join极易致使数据倾斜,进而让任务无法运行。最后,只有放在维度属性极为复杂,且对存储成本有着极致要求的场景当中,才会选用雪花模型。
大厂数仓面试里拉链表是必定会考的试题,十次面试里头有九次都会涉及,面试官要求这位仁兄去编写拉链表更新的SQL,可他仅仅写出了基础的版本,在生产环境当中一定得留意最少三个容易出错的地方。
-- 2026-03-02 拉链表每日更新逻辑
insert overwrite table user_zipper_table
select
t1.user_id,
t1.phone,
t1.status,
t1.start_date,
-- 老记录有新状态变更,结束日期更新为前一天
case
when t1.end_date = '9999-12-31' and t2.user_id is not null
then '2026-03-01'
else t1.end_date
end as end_date
from user_zipper_table t1
left join (
-- 只取当天有变更的用户主键,减少数据量
select user_id from user_update_daily where dt = '2026-03-02'
) t2 on t1.user_id = t2.user_id
union all
-- 新增/变更的数据插入新拉链记录,结束日期设为永久
select
user_id,
phone,
status,
'2026-03-02' as start_date,
'9999-12-31' as end_date
from user_update_daily
where dt = '2026-03-02';
第一个坑在于那是数据闭环方面的问题,老拉链表与增量表进行union操作之后,绝对必然要去校验start_date以及end_date的连续性,绝对绝对不可以出现日期重叠或者断档之类的脏数据。第二个坑是全表扫描性能关乎的问题,若拉链全量表体积极大,直接left join将会致使全表扫描,集群资源会直接被拉满进而触发报警,务必要先去过滤有效数据。

先是第三个坑称作NULL值倾斜陷阱,关联字段user_id要是存在大量NULL值,所有NULL会统统聚合到同一个Reducer,这便直接致使数据倾斜,进而让任务卡死,再说这哥们被问到数据倾斜如何解决时,回答得太过书面化,一眼看去就晓得没处理过百亿级数据。
倘若面对的是百亿级拉链表的更新操作,要是依据简化版SQL去编写,那么生产环境会直接出现运行崩溃,生产环境里存在着三条核心优化策略,扔给面试官就绝对会使他眼前为之怦然一亮。
第一条在历史拉链表里,end_date已然过期的那些处于死亡状态的数据,是绝对没必要参与当日的join计算操作的。在进行join之前,要先加上where end_date = '9999-12-31'这个条件,以此来仅仅过滤出当下有效的数据,再拿去和增量表进行关联,如此一来,数据量会一下子减少90%。
第二条赋予历史拉链表以及每日增量表,皆遵循user_id来实施Hash分桶,举例而言,划分成1000个桶。强制性开启SMB Join,如此一来,join操作就转变成为桶对桶的本地操作,全然规避大规模Shuffle,性能直接实现提升10倍以上。
第三条每天在进行增量更新之后,要记住去做一回按照distribute by进行分桶从而合并那些小文件的操作。不然小文件会一点儿一点儿堆积增长,NameNode承受的压力就会达到极限,HDFS就会直接陷入卡死状态。

当面试官询问客户端写数据期间DataNode出现挂掉的情况应如何处理时,这哥们没办法答上来。实际的流程呈现为这样的状况,客户端只需将数据包推送给首个节点A ,A接着再推送给B ,B随后又推送给C ,这便是被称作Pipeline的管道传输方式。
若在传输进程里B节点处于挂掉状态,那么Pipeline便会即刻中断。客户端会将故障节点B进行剔除,再次构建A至C的Pipeline,接着传输遗留的数据包。待数据全部完成传输后,NameNode会发觉副本数未达要求,会于后台以异步方式复制一个全新副本,补足3副本的规定,整个过程确保数据不会丢失。
这次面试的难度并非处于顶尖水平,然而却极具典型性。我已将录音里所有出现过的考题全部搜罗出来了,你能够依据此来对照瞧瞧自己能够回答上来几个。
在项目架构这一方面,离线数仓跟实时数仓二者之间的区别究竟是什么呢?在面试期间提到了Flink CDC,要是MySQL的Binlog突然间大幅度增加数量,就像双十二大促这种情况,进而致使Flink消费出现积压现象,背负的压力非常之大,此时对你而言会采取怎样的方式来进行优化呢?这些相关问题都是大型企业面试必定会问到的内容,要是回答不上来那就表明实际操作的经验确实是不够的。
读过此篇文章之后,你认为于自身的数仓项目当中,最为容易踏足的坑是拉链表的数据闭环方面的问题,还是因数据倾斜所引发的性能方面的问题呢?欢迎现身评论区去分享你那踩坑的经历。