☰
大数据笔试必看:Hive SQL、海量数据算法与架构设计实战解析
2026/10/21 23:08:02 网站建设 项目流程

最近帮好几个准备跳槽的朋友做模拟面试,发现大家准备大数据笔试时有个共同问题:以为自己在刷题,实际只是在背答案。题目换个问法、换个数据规模,就直接卡壳。

这篇东西把我这两年整理和实战验证过的大数据笔试题目练习(附答案)拿出来拆一遍。不光是给题目和标准答案,更想把每道题背后的考察意图、答题思路、踩坑点讲清楚。内容覆盖SQL与Hive高频题、海量数据处理算法、分布式原理、场景架构设计,以及笔试答题时最容易丢分的细节。适合正在准备大数据开发、数据分析、数据仓库岗位笔试面试的同学,也适合刚入行想系统补基础的朋友。

1. 大数据笔试为什么不能照着后端题库刷

很多同学问我,大数据笔试是不是就是算法题加SQL题。答案是不完全是。大数据岗位的笔试,出题逻辑和普通后端开发有本质区别,理解这个区别,比盲目刷题重要得多。

1.1 大数据笔试到底在考什么

后端笔试的核心是编程语言功底、框架使用、系统设计。大数据笔试则多了一个非常关键的维度:数据规模带来的思维转变。同样的题目,比如说查找TopK,普通开发考察的是排序算法写得对不对,大数据笔试考察的是当数据量达到几十亿、无法全部载入内存时,你的解题思路还成不成立。

这也是为什么很多算法基础不错的同学,在大数据笔试里反而翻车。他们习惯性地写一个Arrays.sort()然后取前K个,在小数据量下没毛病,但面试官追问一句“如果数据量是100亿呢”,这个问题就不是单机排序能解决的了。

大数据笔试的核心考察点,我总结下来主要有四块:

  • SQL与Hive功底:考察数据清洗、统计、窗口函数、行列转换等实际操作能力,这是笔试占比最大、最容易拿分也最容易丢分的部分。
  • 分布式计算原理:HDFS读写流程、MapReduce思想、Spark的RDD依赖关系、数据倾斜处理等,考察你有没有真正理解分布式计算的底层逻辑。
  • 海量数据算法:位图、布隆过滤器、分治、哈希分桶、堆排序的变体,考察你在内存受限条件下的算法设计能力。
  • 场景架构设计:给你一个业务需求,让你设计离线或实时的数据处理链路,考察架构思维和工程落地能力。

1.2 出题人想通过题库筛选什么人

站在出题人的角度想,笔试题目其实就一个目的:在最短的时间内,筛选出真正处理过数据的人,而不是只会背知识点的人。

举个例子,一道看似简单的“计算用户次日留存率”题,新手可能会写出一个逻辑上有缺陷的SQL——先把当天的活跃用户和次日的活跃用户做内连接,然后除以当天活跃用户数。这个答案在数据量小的时候看起来没问题,但实际业务中,用户一天可能有多条活跃记录,如果不先去重就直接计算,留存率会偏低。这种细节,只有真正用SQL处理过埋点日志的人才能意识到。

所以笔试刷题的正确姿势是:每道题不仅要知道标准答案,还要能回答“为什么是这个答案”,以及“换个条件答案会怎么变”。这篇练习里的每道题,我都会按照这个思路展开。

2. SQL与Hive高频题:数据清洗、留存与窗口函数实战

SQL题是大数据笔试的必考项,也是最需要练的部分。这里选了三个最具代表性的高频考点,每个都给了完整题目、建表语句、参考SQL和踩坑说明。

2.1 连续N天登录用户数:窗口函数的经典用法

某App的登录记录表只包含用户ID和登录日期,一天可能有多条记录。现在要找出连续登录3天及以上的用户,并输出用户ID和连续登录起始日期、结束日期、连续天数。

这是真实笔试中出现频率极高的一道题,考察窗口函数的应用。出题人故意说“一天可能有多条记录”,这就是第一个陷阱。如果不去重,直接用日期做差,会出现什么情况?用户同一天登录了三次,日期差为0,但计算连续天数时会被误判成异常数据。

第一步先去重:

SELECT user_id, login_date FROM login_log GROUP BY user_id, login_date;

去重之后,利用一个非常关键的性质:如果用户某几条记录的日期是连续的,那么用“日期减去行号”得到的日期是相同的。举个例子,2026-04-01、2026-04-02、2026-04-03这三天,对应行号如果是1、2、3,日期减行号后都等于2026-03-31。而如果中间断了一天,这个差值就会被打破。

WITH dedup AS ( SELECT user_id, login_date FROM login_log GROUP BY user_id, login_date ), calc AS ( SELECT user_id, login_date, DATE_SUB(login_date, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY login_date)) AS grp FROM dedup ) SELECT user_id, MIN(login_date) AS start_date, MAX(login_date) AS end_date, COUNT(*) AS continuous_days FROM calc GROUP BY user_id, grp HAVING COUNT(*) >= 3;

这个答案有三个得分点:一是对原始表做了去重,二是正确使用窗口函数生成分组标志列,三是用聚合算出每段连续区间的起止时间和天数。答题时,建议先写出SQL,再主动补充一句“如果登录记录是按天去重后的表,可以省去第一步的查重”。这样能体现你考虑边界条件的能力。

实际面试中还有一种变体:求每个用户最长连续登录天数。解法是在上面的基础上再按用户聚合取MAX计数。还有一种更绕的变体,要求统计“连续登录3天以上的用户数”,这就需要在外面再套一层COUNT(DISTINCT user_id),别漏了去重。

2.2 次日留存率:分母分子陷阱

某产品每日的活跃用户表有dt和user_id两个字段,每个用户当天可能活跃多次。求每日的次日留存率,即某天活跃的用户中,第二天依然活跃的比例。

这道题看起来简单,用JOIN就能做,但笔试中的错误率极高。问题就出在“活跃多次”这四个字上。如果表里有重复记录,直接JOIN会产生记录膨胀,算出来的留存率偏高。

正确的做法还是先去重:

WITH active_dedup AS ( SELECT dt, user_id FROM dwd_active_detail GROUP BY dt, user_id ), joined AS ( SELECT a.dt, COUNT(DISTINCT a.user_id) AS day_users, COUNT(DISTINCT b.user_id) AS retained_users FROM active_dedup a LEFT JOIN active_dedup b ON a.user_id = b.user_id AND b.dt = DATE_ADD(a.dt, 1) GROUP BY a.dt ) SELECT dt, day_users, retained_users, ROUND(retained_users / day_users, 4) AS retention_rate FROM joined ORDER BY dt;

这里有几个细节值得注意。LEFT JOIN而不是INNER JOIN,因为某天活跃的用户第二天不一定活跃,如果只统计两边都匹配的记录,分子分母都变小,但分子的“用户集”变成了“当天活跃且次日活跃的用户”,分母应该是一天的全部活跃用户,用INNER JOIN得到的结果会把未留存用户直接过滤掉,留存率算出来还是对的,但统计口径就容易讲不清。笔试时建议写LEFT JOIN,并在注释里说明保留未匹配用户是为了计算分母。

还有一点,COUNT(DISTINCT)虽然在数据量大时性能不好,但在笔试场景中它是保证结果正确性最稳妥的写法。如果数据已经做了唯一性约束,可以简化成COUNT(user_id),否则别冒险。

2.3 行转列与列转行:你写的是笔试答案还是生产代码

某电商平台的订单明细表包含订单ID、商品名称、商品数量。要求把每个订单的商品名称拼接成一列内容,用逗号分隔。同时要求将长表转为宽表,统计每个用户在三个渠道的访问次数。

行转列和列转行是SQL笔试的另一大高频考点,考察的是对聚合函数和控制流程逻辑的熟练度。

第一个场景,按订单聚合商品,使用COLLECT_LIST或COLLECT_SET:

SELECT order_id, CONCAT_WS(',', COLLECT_LIST(item_name)) AS item_list, SUM(item_count) AS total_count FROM dwd_order_item_detail GROUP BY order_id;

COLLECT_SET会自动去重,COLLECT_LIST保留所有记录。如果商品本身是不重复的,两者都可以;如果可能出现同一个商品多行,就需要根据业务语义选择。这里有个更隐蔽的问题:COLLECT_LIST的结果顺序是不可控的,如果业务要求商品按添加时间排序,需要先在子查询里排好序。

第二个场景,行转列,统计某用户行为表里三个渠道的新增访问次数:

SELECT user_id, SUM(CASE WHEN channel = 'app' THEN 1 ELSE 0 END) AS app_cnt, SUM(CASE WHEN channel = 'web' THEN 1 ELSE 0 END) AS web_cnt, SUM(CASE WHEN channel = 'mini_program' THEN 1 ELSE 0 END) AS mini_cnt FROM dwd_traffic_log WHERE date_id = '2026-04-01' GROUP BY user_id;

笔试答题的一个通用技巧是:先写CASE WHEN版本,再用IF函数写成等价形式,最后注明“如果渠道数量很多,推荐用MAP类型动态展开”。这样能体现你对两种写法的掌握,也知道各自的适用场景。很多参考答案只给了一种写法,实际面试中你能补出第二种甚至第三种写法,会很加分。

3. 海量数据处理算法题:三板斧与真实采分点

海量数据题是大数据笔试里最劝退的一部分,因为它在数据结构算法的基础上叠加了“内存放不下”这个硬约束。但这类题的解法其实高度套路化,核心就是三板斧:分而治之、哈希分桶、外部排序。先把三板斧吃透,再逐题展开。

3.1 10亿个关键词统计频次Top100

某搜索引擎的日志中有10亿个关键词,每个关键词的平均长度20字节,内存只有2GB,要求输出出现频次最高的100个关键词。

这道题考察的不仅是算法功底,还有对空间复杂度的敏感性。10亿乘以20字节,原始数据约20GB,2GB内存显然装不下。第一个想到的解法可能是维护一个大小为100的小顶堆,遍历所有数据,每来一个词就更新堆。这个思路本身没错,但漏了一个前置问题:统计数据需要先知道每个词的出现频次,而这需要一个“词到频次”的映射表,这个映射表本身就超过了2GB内存限制。

所以正确的答题链路是:先哈希分桶,再桶内统计,最后合并取Top100。

  • 首先把10亿个关键词通过哈希函数映射到1000个小文件中。映射规则是hash(key) % 1000,相同关键词必然进同一个文件。这一层的目的是把大问题切成1000个能在内存里处理的小问题。
  • 每个小文件约20MB,远小于2GB内存,对每个小文件单独构建哈希表统计词频,维护一个大小为100的堆,得到该文件的Top100。
  • 最后把1000个文件的Top100合并,共10万个词,再维护一个大小为100的堆,二次筛选,最终得到全局Top100。

答题时要把复杂度说出来。第一轮每个文件遍历一遍,总时间复杂度O(N),N是总关键词数;堆操作的时间复杂度O(N log K),K为100,整体可控。空间复杂度方面,每个桶的文件大小不超过内存限制。

这道题还有一个加分项:和面试官沟通“哈希函数的选择”。如果哈希函数选得不好,数据分布可能倾斜,某个桶的文件特别大,照样超出内存。实际的兜底方案是增加分桶数量,或者对超大桶继续递归分桶。笔试时把这一层考虑写出来,会明显和其他考生拉开差距。

3.2 两个大文件找共同URL:从布隆过滤器到分治

两个各有50亿条URL的文件,每条URL约64字节,内存限制为512MB,求两个文件中重复的URL。

如果做题时形成了条件反射,看到“海量数据、内存有限、找交集”,第一反应就应该是两种方案:哈希分治或布隆过滤器。

最稳妥的通用解法是哈希分治:

  • 用hash(url) % 1000把文件A分成1000个小文件,文件B也分成1000个小文件。
  • 因为同一个URL的哈希结果一致,所以A的第i个分文件和B的第i个分文件之间才可能有交集,跨分文件的URL一定不重复。
  • 对每对分文件,把一个载入哈希集合,然后遍历另一个文件逐个判断是否存在,输出重复项。

每对分文件的大小大约50亿 × 64字节 / 1000 = 32MB,两个文件同时载入也就64MB,完全在512MB限制内。这个方案的可靠之处在于不依赖哈希函数是否完美,最坏情况也只是某个分文件偏大,可以继续递归分桶。

布隆过滤器是另一种思路。对文件A的URL建一个位数组,然后把文件B的URL逐个判活。布隆过滤器的问题在于存在误判率,它说“有”不一定真的有,它说“没有”才是一定没有。笔试时如果把布隆过滤器作为唯一方案,容易被追问“误判率怎么处理”,一旦答不上来会扣分。

我的建议是:先答哈希分治作为“一定正确的方案”,再补充布隆过滤器作为“空间更省但可能误判的优化方案”。这种对比式答题在面试中非常讨喜,因为它在展示你知识面的同时,也展示了你对“正确性”和“资源消耗”之间权衡的敏感度。

3.3 HDFS写流程的完整答题链路:五步讲清楚

从1GB文件中读取数据与从1TB文件中读取数据的本质区别,在于分布式文件系统的引入。因此海量需求相关的笔试必考HDFS写流程。先叙述流程,再讲明白“为什么这样设计”才是高分的关键。

标准流程分五步:

  1. 客户端调用DistributedFileSystem的create方法,向NameNode发起上传请求。
  2. NameNode校验权限和目录,若通过则返回一个可写的DataNode列表,并把本次写操作记录进编辑日志。
  3. 客户端将文件按块大小(默认128MB)切分,并从返回的DataNode列表中选择一台作为第一个副本的写入节点,建立数据流管道。
  4. 数据以数据包为单位在管道中依次传递,同时每写一个数据包,DataNode都会向上游节点发送确认,最后一个节点把确认消息逐级返回给客户端。
  5. 写入完成后,客户端调用close方法,NameNode在内存中提交文件元数据。

这五步背下来不难,但笔试时真正拉开差距的是追问环节。面试官常问:如果某个DataNode写入失败怎么办?参考答案是,DataNode会从管道中移除,节点上的未完成数据包会被重新写入其他节点,同时副本数不足时会触发自动补副本机制。回答时不需要把系统源码级别的内容说出来,但至少要把“失败感知、管道重建、副本补齐”这个链路答完整。

还有一道配套变体题:读文件时为什么不需要通知NameNode?答案是读文件时客户端先向NameNode获取文件块与DataNode的映射列表,然后直接与DataNode建立连接读取数据。这个流程里NameNode不参与实际数据传输,这也是HDFS可以支撑大规模并发读取的底层原因。笔试中主动回答这个对比,能让阅卷人看出你理解的是整个读写体系,而不是背了单个流程。

4. 场景架构设计题:从指标需求到落地链路

场景设计题一般出现在笔试的最后,分值最高,也最考察综合能力。这类题目没有唯一标准答案,但有一套完整的答题逻辑:先明确需求,再选技术栈,最后补细节。这部分给两个典型场景的完整答题框架。

4.1 实时UV/PV统计的架构设计:去重是核心难点

某业务需要实时统计全站每小时的访问量PV和独立访客数UV,数据从客户端埋点上报,允许秒级延迟。请画出架构链路并说明关键设计。

回答这类题,先画链路再展开解释。整个数据流程是:客户端SDK采集埋点事件,经网关进入消息队列,实时计算引擎消费消息,聚合结果写入存储系统,最终由前端报表接口查询。

链路里的消息队列选型,通常回答Kafka,理由是三高能力突出——高吞吐、高可靠、高并发。实时计算引擎选Flink,理由是原生的流式处理、毫秒级延迟、精确一次语义保障。存储选型则因查询模式而异,秒级明细查询用Doris或ClickHouse,单纯指标报表用Redis做缓存加HBase兜底亦可。

UV统计的难点在于去重。PV好算,直接累加事件数。UV不行,同一个用户刷新多次页面也只算一个人。实时场景下不能像离线一样用COUNT(DISTINCT)硬算,内存扛不住。

这里有三种可选方案,答题时建议都讲一遍:

  • 精确去重:用Redis的Set结构,以小时加页面为key,把用户ID存入Set,实时计算SCARD获得UV。数据量大时Set过大,需要改进为分片Set。
  • 近似去重:使用HyperLogLog,标准误率约0.81%,内存极小(单个Key约12KB),处理千万级UV毫无压力。
  • 精确且省内存:使用布隆过滤器判断用户是否已统计,误判率控制在可接受范围,但会有轻微多算。

这三个方案说出来之后,一定要给出“实际选型建议”。比如对日活千万以下的业务,Redis Set完全够用;需要极低内存开销时再用HyperLogLog;券商股票类业务,UV不能有误差,则用精确去重。这样答题,等于在向出题人证明你不只是知道技术名词,还知道怎么根据业务做取舍。

4.2 离线数仓分层设计:为什么要分这么多层

某公司的业务数据分散在多个业务库,需要搭建离线数据仓库,支持运营看板、用户行为分析和财务报表三类应用。请设计数仓分层架构,说明每层的职责。

数仓分层这道题在数据分析岗位的笔试中出现频率极高。答题时最忌讳的是只把分层名称列出来:ODS、DWD、DWS、ADS,然后就结束了。一定要说清楚每一层在做什么、为什么需要这一层。

分层设计的核心逻辑是:把复杂的数据加工过程拆解成多步,每一步职责单一,这样便于复用、便于追踪、便于控制数据质量。

  • ODS层(操作数据存储层):原样接入业务库数据,保留最细粒度、最完整的历史。具体操作是采集MySQL的binlog或接口拉取数据,以全量加增量方式落地到Hive或数据湖。这一层不进行任何业务逻辑加工。
  • DWD层(数据明细层):对ODS数据进行清洗、去重、维度退化、规范化。比如统一用户ID格式、过滤无效埋点、转换时区。这一层产出明细事实表和维度表,仍是行级别数据。
  • DWS层(数据汇总层):按主题对DWD明细数据做轻度汇总。比如用户主题,按“用户+日期”维度汇总访问次数、下单次数、GMV等指标。这一层是数据复用的关键,同一份汇总结果可以同时供多个应用查询。
  • ADS层(应用数据层):根据报表、看板、分析模型需求加工成最终结果表。表格结构通常是窄表,索引合理,直接对接BI工具或接口服务。

答题时再补一个加分点:每层之间的数据流转用什么工具。传统方案是Hive SQL加调度工具;时效要求高的场景会引入Spark SQL做批量加速。多维分析需求变多时,把DWS层的一部分结果物化到Doris或ClickHouse,形成“离线数仓加工 + OLAP加速”的组合架构。

最后别忘了说明数据质量监控放在哪一层。很多实际项目会把DWD层作为质量监控的核心层,因为这一层的数据已经标准化,适合做完整性、准确性校验。少讲空话,把这些工程细节写进答案,分数自然就上来了。

5. 笔试答题时最容易丢分的隐性细节

题目都练会了,最后却在笔试环节丢分是最亏的。这两个小节分享一些我在模拟面试和真实笔试里总结出来的实操经验。

5.1 审题不细、答案格式混乱是头号杀手

很多同学做错题不是因为不会,而是因为审题时漏看了关键条件。常见的情况包括:题目说“一天有多条记录”却没去重;题目说“按照降序输出TopN”却忘了排序;题目说“可能为NULL”却没做空值处理。

我的建议是,拿到题目先花一分钟圈出三个东西:输入数据特征、输出格式要求、边界条件描述。比如看到“用户ID为字符串类型”,就要想到排序时不能直接转数字;看到“每天可能多条”,就要在草稿纸上写下“先去重”三个字。这些小习惯,比多刷十道题更能提高正确率。

答案格式同样重要。SQL题先写SELECT还是先写WITH不重要,但整体结构要清楚,尤其是多层嵌套时建议每层缩进。算法题一定要写时间复杂度和空间复杂度,不写等于告诉阅卷人你没想过资源开销。场景设计题,先写结论再展开,比如“本方案使用Kafka和Flink构建实时链路,保证延迟在秒级”,然后再分段展开每部分的选型理由。

5.2 时间分配与带练中总结的刷题法

一套大数据笔试题一般两小时,SQL题占比40%,算法原理题占比30%,场景设计题占比20%,选择题填空题占比10%。时间分配建议按这个比例来,也就是SQL部分安排48分钟,算法原理题36分钟,场景题24分钟,选择题10分钟,剩下的时间检查。

这里有一个很多人没意识到的问题:SQL题既好拿分也容易耗时。不要在一道SQL题上纠缠超过15分钟。如果没思路,先跳过做后面的题,回头再补。笔试系统一般按点给分,留白比错误答案更可怕。

最后分享一个我自己带练时反复验证的刷题方法:限时模拟加复盘,两小时完整模拟一套题,做完必须复盘,复盘重点不是看答案对不对,而是分析当时的思路卡点。是审题漏了条件,是场景设计缺少环节,还是基础知识有盲区。把每一次错误归类,才能在下一次考试时真正规避。

总之,大数据笔试的题目练习没有太多花架子。把高频考点揉碎吃透,把每道题的变体和边界条件想清楚,比追求刷题数量有用得多。希望这组练习能帮你少走一些弯路,真正把笔试变成展示能力的舞台,而不是关卡。

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

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

立即咨询