数据开发每日面试题 Day 1

1.SQL:求连续登录天数

sql 复制代码
login_log(
    user_id,
    login_date
)

同一用户一天可能登录多次。求每个用户最长连续登录天数。

核心考察点: 去重、窗口函数、row_number()、连续区间问题。

sql 复制代码
WITH t1 AS (
    SELECT DISTINCT
           user_id,
           login_date
    FROM login_log
),
t2 AS (
    SELECT
        user_id,
        login_date,
        ROW_NUMBER() OVER (
            PARTITION BY user_id
            ORDER BY login_date
        ) AS rn
    FROM t1
),
t3 AS (
    SELECT
        user_id,
        login_date,
        DATE_SUB(login_date, INTERVAL rn DAY) AS grp
    FROM t2
),
t4 AS (
    SELECT
        user_id,
        grp,
        COUNT(*) AS continuous_days
    FROM t3
    GROUP BY user_id, grp
)
SELECT
    user_id,
    MAX(continuous_days) AS max_continuous_days
FROM t4
GROUP BY user_id;

我会先对 user_id 和 login_date 去重,因为同一天多次登录不能重复计算。然后按用户和日期排序生成 row_number。对于连续日期,日期减去序号后会得到相同的值,因此可以用这个值作为连续区间标识,再统计每段长度,最后取每个用户的最大值。

追问

为什么不能直接 lag()?

可以。lag() 可以判断当前日期和上一日期是不是相差一天,但之后还需要进一步生成分组编号。row_number + 日期偏移 对连续日期问题通常更简洁。

2.Hive 为什么不适合大量 UPDATE / DELETE?

Hive 本质上面向的是大规模离线分析,不是高频事务处理。

Hive 的数据通常以 Parquet、ORC 等文件形式存储在 HDFS 或对象存储中。

而大数据文件往往不是按照"单行记录随机修改"的方式组织的。修改少量记录可能意味着重新生成部分甚至整个数据文件,因此频繁 UPDATE/DELETE 成本很高。

Hive 虽然存在 ACID 表等机制支持事务操作,但它仍然不是为了高并发 OLTP 设计的。

因此典型数仓更常采用:

sql 复制代码
增量写入
覆盖分区
Merge
拉链表

追问

那每天业务数据变化怎么办?

可以按照日期分区,只重算受影响的分区:

sql 复制代码
dt=20260904
dt=20260905

Hive 的数据一般是怎么存储的?

Hive 本身主要提供表结构、元数据管理和 SQL 查询能力,实际数据通常以文件形式存储在 HDFS 或对象存储中。

文件格式常用 ORC 和 Parquet,它们都是列式存储格式。相比行式存储,列式存储在查询部分字段时可以减少不必要的数据读取,也更有利于压缩,因此比较适合 Hive 这种以分析查询为主的场景。

ORC 对 Hive 生态的支持比较成熟,Parquet 的跨引擎兼容性更好,在 Hive、Spark、Trino 等系统中都很常见。

至于底层存储,传统 Hadoop 架构一般使用 HDFS。HDFS 会把大文件切分成 Block,分散存储到多个节点,并通过副本机制提供容错能力。

现在云环境下也经常使用 S3、OSS 等对象存储代替 HDFS,这样可以实现计算和存储分离,计算资源可以独立扩缩容。

面试问题 核心回答
Parquet / ORC 是什么? 列式文件格式
为什么适合 Hive? 列裁剪、压缩率高、减少 I/O,适合分析查询
ORC 和 Parquet 区别? ORC 与 Hive 生态结合成熟;Parquet 跨引擎生态更广
HDFS 是什么? 分布式文件系统,Block 分块 + 多节点存储 + 副本容错
Hive 数据存在 Hive 里吗? 严格来说实际数据通常存在 HDFS/对象存储的文件中,Hive 管理表结构和元数据并提供查询能力
HDFS 和 Parquet 什么关系? 不是同一层级:Parquet 是文件格式,HDFS 是文件存储的位置/系统
为什么现在用对象存储? 存算分离、弹性扩缩容、降低集群存储维护成本

3.数仓为什么一定要分层?

数仓分层的核心不是为了增加表,而是为了降低不同处理阶段之间的耦合,提高数据复用性和可维护性。

sql 复制代码
业务系统
   ↓
ODS
   ↓
DWD
   ↓
DWS
   ↓
ADS

ODS:

尽量保持源系统原貌。

解决:

原始数据是什么?

DWD:

完成清洗、标准化、维度退化等,形成较细粒度的事实数据。

解决:

发生了什么业务行为?

DWS:

围绕主题做公共聚合。

解决:

某个业务主题有哪些公共指标?

ADS:

直接服务报表、应用、接口。

重点是职责边界清晰。

4.Hive 出现数据倾斜,你怎么判断和处理?

如何判断?

查看任务执行情况:

大部分 Task 已完成,少数 Task 长时间运行;

不同 Reducer 输入数据量差异巨大;

某些 Key 出现频率异常高;

Shuffle Read 数据明显不均衡。

怎么处理?

需要根据倾斜来源处理。

热点 Key 聚合:加盐,两阶段聚合

Join 倾斜:

小表:

MapJoin / Broadcast Join

避免大规模 Shuffle。

NULL 倾斜:

大量 NULL 可能全部进入同一个分区。

如果 NULL 没有业务意义,可以过滤;或者给 NULL 增加随机值分散。

为什么加盐可以解决?

因为默认相同 Key 会通过 Hash 被发送到同一个 Reducer。

加盐改变 Key:

A → A_1 / A_2 / A_3

从而分散到多个 Reducer。

5. Spark 中什么时候会发生 Shuffle?

当数据需要跨分区重新分布时,一般会产生 Shuffle。

sql 复制代码
groupByKey
reduceByKey
join
distinct
repartition
sortByKey

shuffle涉及:

sql 复制代码
序列化
网络传输
磁盘 I/O
排序
反序列化

Spark 优化中一个非常重要的原则就是:

尽量减少不必要的 Shuffle。

reduceByKey 和 groupByKey 哪个更好?

通常 reduceByKey。

因为它可以在 Map 端先做局部聚合:

sql 复制代码
Map-side Combine

减少 Shuffle 数据量。

6. Kafka 为什么这么快?

Kafka 高吞吐主要来自几个方面:

1.顺序写磁盘

Kafka 日志采用 append-only:

sql 复制代码
message1
message2
message3
→ append

相比随机磁盘访问,顺序 I/O 性能非常高。

Page Cache

大量数据通过操作系统 Page Cache 处理,减少用户态应用自己维护缓存的成本。

批量处理

Producer 可以将多条消息 Batch 后发送:

sql 复制代码
1 message × 1000 requests

变成:

sql 复制代码
1000 messages × 1 batch

显著降低网络调用成本。

零拷贝

发送日志数据时可以减少:

Kernel → User → Kernel

之间不必要的数据复制。

Partition 并行

不同 Partition 可以并行读写。

追问

Partition 越多越好吗?

不是。

Partition 增加可以提高并行度,但也会增加:

文件句柄;

Broker 元数据;

Leader election 成本;

Consumer rebalance 成本。

7. Kafka Consumer Group 到底解决什么问题?

同一个 Consumer Group 内:

一个 Partition 同一时间只能被一个 Consumer 消费。

追问

4 Partition,10 Consumer 会怎样?、

只有最多 4 个 Consumer 真正工作。

Consumer 并行度 ≤ Partition 数量。

8. CDC 和每天定时抽数有什么区别?

考察点: CDC、Binlog、增量同步、实时数仓。

CDC:

sql 复制代码
INSERT
UPDATE
DELETE

发生以后,从数据库日志中捕获变化。

例如 MySQL:

sql 复制代码
Binlog
 ↓
CDC
 ↓
Kafka

CDC 优势
延迟低;

不需要不断扫描业务表;

能够捕获:

sql 复制代码
INSERT
UPDATE
DELETE

的变化语义。

但 CDC 也更复杂

需要处理:

sql 复制代码
重复事件
乱序
Schema Evolution
断点恢复
Exactly-once

追问

为什么不直接让业务系统把数据发 Kafka?

可以,而且很多系统就是这么设计。

但是 CDC 的优势是:

不要求侵入原有业务代码。

对于已经存在的大量传统业务系统尤其有价值。

考察点: Stateful Streaming、容错。

Checkpoint 保存的是 Flink 作业在某个一致性时刻的状态快照。

恢复时:

Checkpoint State

对应数据源位置

共同恢复。

Kafka Source 中尤其重要的是:

消费到哪个 offset

追问
Checkpoint 和 Savepoint 区别?

Checkpoint:

系统自动进行,主要用于故障恢复。

Savepoint:

通常由用户主动触发,更偏向版本升级、迁移、维护。

10. Redis 已经有数据了,为什么还需要 Doris?

Redis:

适合:

sql 复制代码
key → value

例如:

sql 复制代码
user:1001:today_order_amount → 3280

特点:

极低延迟点查。

Doris:

适合:

sql 复制代码
SELECT city,
       category,
       SUM(amount)
FROM orders
WHERE dt BETWEEN ...
GROUP BY city, category;

特点:

大规模 OLAP 聚合分析。

sql 复制代码
Redis → 快速服务/缓存
Doris → 分析查询

面试口述一句话版本

Redis 更适合低延迟 Key-Value 查询,而 Doris 是面向分析型查询的 MPP OLAP 数据库,因此实时链路可以把部分热点指标写 Redis 服务在线查询,同时将明细或聚合数据写 Doris 支撑复杂分析。

11. 银行数仓场景:上游字段发生变化,你怎么办?

考察点: 数据治理、Schema Change、影响分析、生产意识。

假设省联社下发表原本:

sql 复制代码
customer_id varchar(20)

突然改成:

sql 复制代码
customer_id varchar(40)

甚至字段含义发生变化。

真正工作需要先做影响分析。

推荐流程

第一步:

确认变化:

sql 复制代码
字段类型?
长度?
是否允许 NULL?
业务含义?
数据范围?
生效日期?
历史数据是否回刷?

第二步:
分析血缘。

sql 复制代码
ODS
 ↓
DWD
 ↓
DWS
 ↓
ADS
 ↓
报表/接口

哪些表、存储过程、ETL Job、报表依赖这个字段。

第三步:
评估兼容性。

如果只是:

sql 复制代码
varchar(20) → varchar(40)

通常风险较低。

如果:

sql 复制代码
customer_id

含义从"客户号"变成"统一客户号",那就是业务语义变化,危险得多。

第四步:
修改并测试。

包括:

sql 复制代码
开发环境验证
数据量核对
NULL检查
重复检查
上下游对账

第五步:

安排生产上线和回滚方案。

追问

如果已经导致当天报表错误怎么办?

先控制影响范围,暂停错误结果继续下发;定位受影响批次和表;修复逻辑后重跑对应链路,并对重跑前后数据进行对账;最后分析为什么字段变化没有提前被数据质量或 Schema 检查发现。

12. 场景题:昨天任务跑 20 分钟,今天突然跑了 3 小时,你怎么排查?

第一层:先判断变化来自哪里

对比昨天和今天

sql 复制代码
数据量
SQL
执行计划
集群资源
上游数据
分区数量
Task 数量

第二层:看任务运行阶段

例如 Spark/Hive:

sql 复制代码
Map 慢?
Shuffle 慢?
Reduce 慢?
少数 Task 慢?
所有 Task 都慢?

如果:

99% Task 完成,1 个 Reducer 卡两小时

高度怀疑:

数据倾斜

如果:

所有 Task 都比昨天慢

更可能:

sql 复制代码
集群资源不足
I/O问题
网络问题
数据量整体暴涨

第三层:检查数据变化

sql 复制代码
某分区异常
NULL暴增
热点Key
重复数据
上游补历史数据

第四层:检查 SQL / 执行计划

sql 复制代码
新增 JOIN
JOIN 条件变化
过滤条件失效
分区裁剪失效
小表突然变成大表

第五层:根据原因处理

sql 复制代码
热点 Key:
加盐 / 两阶段聚合。

小表 Join:
Broadcast / MapJoin。

数据量增长:
增加并行度、调整资源、优化分区。

SQL:
Predicate Pushdown、Partition Pruning、减少 Shuffle。

资源:
查看集群资源竞争并调整任务调度。

面试口述模板:

我不会一开始就假设是某一个问题,而会先和正常批次做对比。首先确认代码、数据量和集群资源有没有变化,然后通过执行日志判断耗时集中在哪个 Stage 和 Task。如果只有少量 Task 明显拖尾,我会重点排查数据倾斜;如果整体都变慢,则检查资源、I/O 和数据量。之后再检查上游数据分布、分区以及 SQL 执行计划,最后针对具体瓶颈做优化,并通过重跑和指标对比验证优化是否有效。

相关推荐
崖边看雾1 小时前
Hadoop —— MapReduce完整工作流程
大数据·mapreduce
崖边看雾1 小时前
Hadoop —— HDFS 读流程
大数据·hadoop·hdfs
2601_960356382 小时前
消费者洞察岗项目准备清单:SQL、问卷、用户分层与可视化
大数据·数据库·sql
金融小师妹5 小时前
AI趋势识别:黄仁勋宣布“AGI时代”到来,Astra能力跃迁背后的AI安全边界
大数据·python·深度学习·重构·逻辑回归
IT研究室9 小时前
最新大数据毕业设计选题推荐-基于大数据的城市交通流量数据可视化分析-大数据-Spark-Hadoop-Bigdata
大数据·信息可视化·课程设计
面向Google编程10 小时前
Apache Iceberg Variant 类型:v3 半结构化数据不再「二选一」
大数据·后端
三84410 小时前
redis防御加固与安全基线
数据库·redis·安全·应急响应·防御
lhldsg10 小时前
全民健身解决方案小程序开发:从0到1的技术实战
java·数据库·需求分析