📝 数据开发面经1
1. 你熟悉SQL吗?
💡 回答:我对 SQL 有较为扎实的掌握和丰富的实践经验,从基础语法到复杂查询场景都有实际应用。在日常学习和项目开发中,经常使用 SQL 完成数据提取、清洗、转换及分析工作,熟练编写多表关联、子查询、聚合函数、开窗函数等复杂语句,能够根据业务需求设计高效的查询语句并进行性能优化。
例如在 XX 数据处理项目中,曾使用 SQL 实现千万级用户行为数据的筛选与汇总,通过索引优化和查询逻辑调整,将原本 30 分钟的查询时间缩短至 5 分钟内;同时也熟悉 SQL 的事务管理、存储过程及触发器的使用,能结合业务场景实现数据的批量处理与自动化操作,确保数据的一致性和准确性。
2. SQL表关联有哪些?
🔗 回答:SQL 表关联本质是通过表间的共同字段(通常是主键与外键)建立连接,从而整合多个表的数据进行联合查询,核心关联方式围绕“连接条件”和“数据匹配规则”展开,主要包括以下几类:
-
内关联(INNER JOIN):只返回两个表中满足连接条件的交集数据,是最常用的关联方式,适用于需要精准匹配双方数据的场景。
-
外关联:以其中一个表为基准,返回基准表的全部数据,以及关联表中满足条件的数据,未匹配到的字段显示为 NULL,又细分为左外关联(LEFT JOIN,左表为基准)、右外关联(RIGHT JOIN,右表为基准)、全外关联(FULL JOIN,两表均为基准,返回双方全部数据)。
-
交叉关联(CROSS JOIN):无需指定连接条件,返回两个表的笛卡尔积,即左表每一行与右表每一行都组合成一条数据,结果集数量为两表行数的乘积,实际业务中需谨慎使用,通常结合 WHERE 条件筛选有效数据。
-
自关联(SELF JOIN):将表与自身进行关联,本质是把一张表当作两张表使用,需通过表别名区分,适用于查询表内具有层级或关联关系的数据,比如员工表中查询“员工及其直属领导”的信息。
3. JOIN分类
📊 回答:JOIN 作为 SQL 表关联的核心关键字,其分类与表关联方式一一对应,核心依据是“数据匹配逻辑”和“基准表选择”,具体分类及特点如下:
-
内连接(INNER JOIN / JOIN): - 逻辑:仅保留两个表中满足 ON 条件的“匹配行”,不匹配的行直接过滤。 - 语法:SELECT * FROM 表 A INNER JOIN 表 B ON 表 A. 字段 = 表 B. 字段; - 场景:需要获取两个表中“都存在”的关联数据,比如订单表与用户表关联查询“有订单记录的用户信息”。
-
左外连接(LEFT JOIN / LEFT OUTER JOIN): - 逻辑:以左表为基准,保留左表的全部行,右表仅保留匹配 ON 条件的行,未匹配行的右表字段为 NULL。 - 语法:SELECT * FROM 表 A LEFT JOIN 表 B ON 表 A. 字段 = 表 B. 字段; - 场景:需要展示左表完整数据,同时关联右表信息,比如用户表左连订单表,查询“所有用户及其订单情况(包括无订单用户)”。
-
右外连接(RIGHT JOIN / RIGHT OUTER JOIN): - 逻辑:与左外连接相反,以右表为基准,保留右表全部行,左表仅保留匹配行,未匹配行左表字段为 NULL。 - 语法:SELECT * FROM 表 A RIGHT JOIN 表 B ON 表 A. 字段 = 表 B. 字段; - 场景:以右表数据为核心,比如订单表右连商品表,查询“所有订单及对应商品信息(包括商品信息缺失的订单)”。
-
全外连接(FULL JOIN / FULL OUTER JOIN): - 逻辑:保留两个表的全部行,匹配的行合并,未匹配的行对应关联表字段为 NULL,相当于左外连接与右外连接的并集。 - 语法:SELECT * FROM 表 A FULL JOIN 表 B ON 表 A. 字段 = 表 B. 字段; - 场景:需要完整展示两个表的所有数据及关联关系,比如统计“所有用户和所有订单的关联情况,包括无订单用户和无对应用户的订单”。
-
交叉连接(CROSS JOIN): - 逻辑:无连接条件,返回两表笛卡尔积,结果集行数 = 表 A 行数×表 B 行数。 - 语法:SELECT FROM 表 A CROSS JOIN 表 B;(或直接写 SELECT FROM 表 A, 表 B;) - 场景:需生成所有可能的组合数据,如“商品表与地区表交叉连接生成所有商品在各地区的初始数据”,通常需搭配 WHERE 条件过滤无效组合。
注意:部分数据库(如 MySQL)不直接支持 FULL JOIN,可通过 LEFT JOIN UNION RIGHT JOIN 实现同等效果。
4. CASE WHEN了解吗?
🔍 回答:CASE WHEN 是 SQL 中用于实现“条件判断”的核心函数,相当于程序中的“if-else”逻辑,能够根据不同条件返回不同结果,灵活应用于数据分类、值替换、条件聚合等场景,其语法分为“简单 CASE”和“搜索 CASE”两种,具体如下:
1. 基本语法
-
简单 CASE 表达式:针对单个字段的固定值匹配,语法简洁。 格式:CASE 字段名 WHEN 值 1 THEN 结果 1 WHEN 值 2 THEN 结果 2 ... ELSE 默认结果(可选) END [别名]
-
搜索 CASE 表达式:支持复杂条件判断(如范围、多字段组合),适用场景更广。 格式:CASE WHEN 条件 1 THEN 结果 1 WHEN 条件 2 THEN 结果 2 ... ELSE 默认结果(可选) END [别名]
2. 核心用途及示例
-
数据分类 / 标签化:如根据用户年龄划分年龄段 SELECT 用户名, 年龄, CASE WHEN 年龄 < 18 THEN '未成年' WHEN 年龄 BETWEEN 18 AND 35 THEN '青年' WHEN 年龄 BETWEEN 36 AND 55 THEN '中年' ELSE '老年' END AS 年龄分段 FROM 用户表;
-
值替换 / 数据清洗:如将订单状态码转换为中文 SELECT 订单号, CASE 状态码 WHEN 0 THEN '待支付' WHEN 1 THEN '已支付' WHEN 2 THEN '已取消' ELSE '异常' END AS 订单状态 FROM 订单表;
-
条件聚合统计:如按不同条件统计数量(替代多次子查询) SELECT COUNT(CASE WHEN 性别 = '男' THEN 1 END) AS 男性数量, COUNT(CASE WHEN 性别 = '女' THEN 1 END) AS 女性数量, COUNT(CASE WHEN 注册时间 > '2024-01-01' THEN 1 END) AS 新用户数量 FROM 用户表;
注意:ELSE 子句可选,若省略,未匹配到条件的结果会返回 NULL;CASE WHEN 可嵌套使用,但需控制层级避免逻辑复杂,同时支持在 SELECT、WHERE、ORDER BY 等子句中使用。
5. 开窗函数中的排序函数
⚡ 回答:开窗函数(Window Function)的核心是“在保留原表行数的基础上,对数据进行分组计算”,其中排序函数是高频应用类型,主要用于对分组内的数据进行排序并生成排名,常用的排序函数有 ROW_NUMBER()、RANK()、DENSE_RANK(),三者的核心区别在于“处理并列排名时的逻辑不同”,具体如下:
1. 通用语法结构
排序函数 OVER (PARTITION BY 分组字段 ORDER BY 排序字段 [ASC/DESC]) AS 排名别名 - PARTITION BY:可选,用于指定“分组字段”,若省略则对全表排序; - ORDER BY:必选,指定分组内的“排序字段”及升降序(默认 ASC 升序)。
2. 三大排序函数对比
3. 实际应用场景
-
ROW_NUMBER():适用于“取分组内前 N 条唯一数据”,如“各部门业绩前 3 的员工”(即使业绩相同也只取前 3); 示例:SELECT * FROM (SELECT 部门, 姓名, 业绩, ROW_NUMBER() OVER (PARTITION BY 部门 ORDER BY 业绩 DESC) AS rn FROM 员工表 ) t WHERE rn ≤3;
-
RANK():适用于“需要体现并列排名及排名间隔”的场景,如“考试排名(并列第一后直接第三)”;
-
DENSE_RANK():适用于“需要体现并列排名但无间隔”的场景,如“评选等级(并列 A 级后直接 B 级)”。
6. 问项目
7. 问比赛
📝 数据开发面经2
1. 简单介绍一下项目
💬 回答:可参考面经 1 中“问项目”的 STAR 法则,结合自身最贴合数据开发的项目精简回答,突出核心技术和价值,示例如下:
我参与过的核心项目是“企业客户信用评估数据平台”开发,服务于银行风控部门,目标是整合企业的工商、税务、信贷三大类数据,构建信用评估指标体系,辅助风控人员判断企业贷款风险。我作为数据开发工程师,主要负责数仓构建和 ETL 流程开发。
具体工作中,我基于 Kimball 理论设计数仓分层(ODS-DWD-DWS-DM),用 Hive 实现工商表与税务表的关联清洗,通过 Sqoop 同步 MySQL 业务数据至 HDFS,用 Spark SQL 开发“企业近 3 年纳税增长率”“信贷逾期次数”等 20 余个核心指标的计算逻辑。针对数据倾斜问题,采用“大表拆分成小表 + 广播连接”的优化方案,将 ETL 任务执行时间从 4 小时压缩至 50 分钟。
项目上线后,风控部门的企业信用评估效率提升 70%,逾期贷款识别准确率提升 20%,累计帮助银行减少潜在坏账损失超 5000 万元。期间我也主导解决了“历史信贷数据格式不统一”的问题,通过正则表达式和字典映射完成数据标准化,确保了指标计算的准确性。
2. 假设现在有一张表数据重复,用两种方式去重
🗑️ 回答:数据去重需结合“重复定义”(完全重复 / 部分字段重复)选择方案,以下针对最常见的“完全重复行”和“指定字段重复(需保留一条)”两种场景,提供两种核心去重方式,附具体语法:
场景:表名user_info,存在重复数据,需保留唯一记录
方式一:使用DISTINCT关键字(适用于“完全重复行”去重)
核心逻辑:DISTINCT 会过滤掉 SELECT 子句中所有字段完全相同的重复行,仅保留一行,语法简洁,适用于重复行判断标准为“全字段一致”的场景。
语法: -- 1. 直接查询去重后的数据 SELECT DISTINCT FROM user_info; -- 2. 若需将去重后的数据插入新表 CREATE TABLE user_info_distinct AS SELECT DISTINCT FROM user_info;
注意:DISTINCT 作用于所有查询字段,若仅需按部分字段去重(如“同一用户 ID 仅保留一条”),则不适用此方式。
方式二:使用开窗函数ROW_NUMBER()(适用于“按指定字段去重,保留一条”)
核心逻辑:按“去重基准字段”(如 user_id)分组,对组内数据按任意规则(如创建时间)排序,用 ROW_NUMBER() 分配唯一序号,取序号为 1 的记录即为去重后的数据,灵活度高,可控制保留哪条数据(如最新 / 最早记录)。
语法: -- 1. 子查询方式,保留每个 user_id 的最新记录(按 create_time 降序) SELECT FROM ( SELECT , ROW_NUMBER()OVER (PARTITION BY user_id ORDER BY create_time DESC) AS rn FROM user_info ) t WHERE rn = 1; -- 2. 若需覆盖原表去重(需谨慎,建议先备份) CREATE TABLE user_info_temp AS SELECT FROM ( SELECT , ROW_NUMBER()OVER (PARTITION BY user_id ORDER BY create_time DESC) AS rn FROM user_info ) t WHERE rn = 1; DROP TABLE user_info; ALTER TABLE user_info_temp RENAME TO user_info;
补充方式:若使用 MySQL,也可通过“GROUP BY + 聚合函数”去重(需确保非分组字段用聚合函数处理),如 SELECT user_id, MAX(create_time) AS create_time, MAX(name) AS name FROM user_info GROUP BY user_id; 但此方式需指定所有非分组字段的聚合规则,不如开窗函数灵活。
3. 数仓分层及其作用
🏗️ 回答:数据仓库分层是基于“数据生命周期”和“业务需求”,将数据按处理阶段拆分,核心目标是“解耦数据处理流程、提升数据复用性和开发效率”,行业内主流采用“四层 / 五层架构”,以四层架构(ODS-DWD-DWS-DM)为例,各层定义及作用如下:
补充:部分企业会在 DWS 和 DM 之间增加“ADS 层(应用数据层)”,专门存放面向应用的最终数据,核心作用与 DM 层类似,本质是更精细的分层拆分。
4. 数仓为什么要分层
❓ 回答:数仓分层并非“技术炫技”,而是基于“数据管理效率”“业务支撑能力”“开发维护成本”等核心需求设计的,其核心价值可从以下 5 个维度解释:
-
解耦数据处理流程,提升开发效率:分层后,每一层仅专注于“特定处理任务”(如 ODS 存原始数据、DWD 做清洗),开发人员无需关注全流程数据变化。例如,当业务系统数据格式变更时,仅需修改 ODS 到 DWD 的同步逻辑,不影响 DWS 及以上层级的开发,降低代码耦合度。
-
实现数据复用,减少重复计算:DWS 层的聚合数据可支撑多个 DM 层的业务需求,避免不同部门为计算“同一指标”(如用户活跃度)重复加工数据。例如,运营部门的日活报表和风控部门的用户行为分析可共用 DWS 层的“用户日行为汇总数据”,减少计算资源浪费。
-
保障数据质量,便于问题定位:分层后数据处理链路清晰,若某一层数据出现问题(如指标异常),可快速定位到对应层级(如 DWD 层清洗错误还是 DWS 层聚合逻辑错误),而非在杂乱的全量数据中排查。同时,DWD 层的清洗过程可统一管控数据质量,避免脏数据流入上层。
-
支撑灵活的业务需求,提升响应速度:面对多变的业务需求(如突然需要“用户周活跃度”指标),可基于 DWD 层明细数据快速计算,或基于 DWS 层日活数据进一步聚合,无需从原始数据重新加工,大幅提升业务响应速度。
-
隔离原始数据与应用数据,降低系统风险:ODS 层隔离了业务系统和数仓,避免数仓的查询、加工操作影响业务系统性能;同时,DM 层仅提供应用所需的最终数据,避免原始数据直接暴露,保障数据安全。
总结:数仓分层的核心是“将复杂问题拆解为简单任务”,通过分层实现“数据的有序管理、高效复用和灵活支撑”,是大数据体系化建设的核心基础。
5. 缓慢变化维是指什么,常见处理方式
🔄 回答:在数据仓库中,“维度”是描述业务实体的属性(如用户维度的姓名、地址,商品维度的类别、价格),缓慢变化维(Slowly Changing Dimension,简称 SCD)是指“维度属性随时间发生变化,但变化频率较低”的维度,例如用户地址变更、商品价格调整,这类变化若不处理会导致历史数据统计失真,常见处理方式分为 SCD Type 1~Type 6,核心常用的是前 3 种:
1. 缓慢变化维的核心特点
- 变化频率低:不同于订单等事实数据的高频变化,维度属性通常数月或数年变化一次; - 变化需追溯:若直接覆盖旧值,会导致“基于历史维度”的统计(如“去年某商品所属类别的销售额”)无法准确计算。
2. 常见处理方式(核心3种)
3. 示例说明(SCD Type 2最常用)
用户维度表 user_dim,用户 ID=1001 的用户地址从“北京市”变更为“上海市”(2024-01-01 生效):
变更前记录: user_id | user_name | address | start_time | end_time | is_current 1001 | 张三 | 北京市 | 2023-01-01 | 9999-12-31 | 1
变更后记录: 1001 | 张三 | 北京市 | 2023-01-01 | 2023-12-31 | 0 1001 | 张三 | 上海市 | 2024-01-01 | 9999-12-31 | 1
查询 2023 年该用户的订单地域时,通过“订单时间介于 user_dim.start_time 和 user_dim.end_time”关联,即可获取当时的“北京市”地址,保障统计准确。
6. ETL分别指哪三个步骤
🔧 回答:ETL 是数据仓库建设的核心流程,贯穿数据从“业务系统”到“数仓应用”的全链路,其三个字母分别对应“Extract(抽取)”“Transform(转换)”“Load(加载)”,三个步骤环环相扣,每个步骤都有明确的目标和常用技术,具体如下:
-
Extract(数据抽取): - 核心目标:从各类业务源系统(如 MySQL、Oracle、Redis、日志文件、API 接口等)中,高效、准确地提取数据,分为“全量抽取”和“增量抽取”两种方式。 - 关键要求:1. 不影响源系统性能(如避免在业务高峰期执行全量抽取);2. 保证数据完整性(不丢失数据);3. 支持多种数据源类型。 - 常用工具 / 技术:Sqoop(用于关系型数据库与 HDFS 的抽取)、Flume(用于日志数据抽取)、DataX(多源数据同步工具)、API 接口调用(如 RESTful API 抽取第三方数据)。 - 抽取策略:全量抽取(适用于数据量小、无增量标识的场景,如商品字典表);增量抽取(适用于数据量大的场景,通过时间戳、自增 ID、日志 CDC 等方式识别新增 / 变更数据)。
-
Transform(数据转换): - 核心目标:将抽取的“原始、杂乱”数据,按数仓模型要求进行清洗、转换、整合,使其成为“干净、标准、结构化”的数据,是 ETL 中最复杂的步骤。 - 核心操作:1. 数据清洗(去重、补全缺失值、修正异常值,如将“年龄 =-1”修正为 NULL);2. 数据转换(字段类型转换、格式标准化,如将“日期字符串‘20240101’转换为‘2024-01-01’”);3. 数据整合(多表关联、字段拆分 / 合并,如将“姓名 + 手机号”拆分为两个字段);4. 指标计算(如基于订单明细计算“订单总金额”)。 - 常用工具 / 技术:Hive SQL、Spark SQL、Flink SQL(批量 / 实时转换)、Python(Pandas,适用于小批量数据转换)。
-
Load(数据加载): - 核心目标:将转换后的干净数据加载到数据仓库的对应分层(如 ODS、DWD、DWS)中,确保数据加载的高效性和一致性。 - 加载方式:1. 全量加载(覆盖目标表数据,适用于 ODS 层原始数据);2. 增量加载(仅加载新增 / 变更数据,适用于 DWD、DWS 层);3. 分区加载(按时间、地域等字段分区存储,提升查询效率,如 Hive 的分区表加载)。 - 常用工具 / 技术:Hive Load、Spark Write、SQL 的 INSERT 语句、数据仓库自带的加载工具(如 Greenplum 的 gpload)。 - 关键要求:支持事务(避免加载过程中数据丢失或不一致)、支持失败重试机制、加载后需进行数据校验(如行数比对、关键字段非空校验)。
补充:随着实时数仓的发展,传统离线 ETL 已逐渐延伸出“ELT”模式(Extract-Load-Transform),即先将原始数据加载到数仓,再在数仓中进行转换,核心优势是利用数仓的计算能力处理大规模数据,适用于实时性要求高的场景。
7. 星型模型和雪花模型的概念及其区别
❄️ 回答:星型模型和雪花模型是数据仓库中两种经典的“维度建模”方式,核心区别在于“维度表的层级结构”,两种模型各有优劣,需结合业务场景选择,具体概念及区别如下:
1. 核心概念
-
星型模型(Star Schema): 以“事实表”为中心,所有“维度表”直接与事实表关联,维度表之间没有关联关系,维度表通常是“扁平化”的,不进行进一步拆分,整体结构像“星星”,因此得名。 - 事实表:存储业务核心指标(如订单金额、销量)和关联维度的外键(如用户 ID、商品 ID、时间 ID); - 维度表:围绕事实表,存储单一维度的属性(如用户表存储用户 ID、姓名、地址;商品表存储商品 ID、名称、类别)。
-
雪花模型(Snowflake Schema): 在星型模型的基础上,将“部分维度表进一步拆分为多个层级维度表”,维度表之间存在关联关系,形成“层级结构”,整体结构像“雪花”。 - 例如:星型模型中“商品维度表”包含商品 ID、名称、类别名称;雪花模型会将其拆分为“商品表”(商品 ID、名称、类别 ID)和“商品类别表”(类别 ID、类别名称),商品表通过类别 ID 关联商品类别表,形成维度层级。
2. 核心区别
3. 示例对比
以“订单分析”场景为例: - 星型模型:事实表(订单 ID、用户 ID、商品 ID、时间 ID、订单金额)→ 关联用户表(用户 ID、姓名、地址)、商品表(商品 ID、名称、类别名称)、时间表(时间 ID、日期、月份); - 雪花模型:事实表(订单 ID、用户 ID、商品 ID、时间 ID、订单金额)→ 关联用户表(用户 ID、姓名、地区 ID)→ 地区表(地区 ID、省份、城市);商品表(商品 ID、名称、类别 ID)→ 类别表(类别 ID、类别名称);时间表(同星型)。
8. Hadoop有哪些组件
🖥️ 回答:Hadoop 是大数据技术的核心框架,基于“分布式存储”和“分布式计算”两大核心能力,包含“核心组件”和“生态组件”,共同构成完整的大数据处理体系,具体组件及作用如下:
1. 核心组件(Hadoop Core)
核心组件是 Hadoop 的基础,支撑分布式存储和计算的核心能力,主要包括 HDFS 和 YARN:
-
HDFS(Hadoop Distributed File System,分布式文件系统): - 核心作用:解决“大规模数据的分布式存储”问题,将数据分散存储在集群的多个节点上,通过副本机制保障数据可靠性。 - 核心架构:1. NameNode(主节点):管理文件系统的元数据(如文件名、存储路径、副本数),不存储实际数据;2. DataNode(从节点):存储实际数据块(默认块大小 128MB),执行数据的读写操作;3. SecondaryNameNode:辅助 NameNode,定期合并元数据日志,避免元数据丢失。 - 特点:适合存储大文件(GB/TB 级),不适合小文件;采用“一次写入、多次读取”模式,不支持随机修改。
-
YARN(Yet Another Resource Negotiator,资源调度系统): - 核心作用:负责 Hadoop 集群的“资源管理”和“任务调度”,统一管理集群的 CPU、内存等资源,为各类计算任务分配资源。 - 核心架构:1. ResourceManager(主节点):全局资源管理器,接收任务请求,分配资源;2. NodeManager(从节点):每个节点的资源管理器,负责本节点的资源监控和任务执行;3. ApplicationMaster:每个计算任务的“应用管理器”,向 ResourceManager 申请资源,协调 NodeManager 执行任务。 - 特点:支持多计算框架(如 MapReduce、Spark、Flink),实现资源的统一调度和共享。
-
MapReduce(分布式计算框架): - 核心作用:基于“分而治之”思想,实现大规模数据的分布式并行计算,是 Hadoop 早期的核心计算组件。 - 核心流程:1. Map 阶段:将输入数据拆分,并行处理为键值对;2. Shuffle 阶段:将 Map 输出的键值对按键分组,分发到不同 Reduce 节点;3. Reduce 阶段:对分组后的键值对进行聚合计算,输出结果。 - 特点:适合离线批量计算,稳定性高,但实时性差,目前逐渐被 Spark、Flink 等框架替代。
2. 核心生态组件(Hadoop Ecosystem)
围绕核心组件,Hadoop 生态衍生出多个专项组件,满足不同场景的需求:
-
Hive:基于 Hadoop 的数据仓库工具,将 SQL 语句转换为 MapReduce/Spark 任务执行,实现“用 SQL 操作大数据”,核心用于离线数据仓库构建。
-
HBase:基于 HDFS 的分布式列存储数据库,支持“随机读写”和“实时查询”,适合存储非结构化 / 半结构化数据(如用户行为日志),常用于实时数仓场景。
-
Sqoop:用于“关系型数据库”与“Hadoop 生态”之间的数据同步工具,支持将 MySQL/Oracle 数据导入 HDFS/Hive,或从 Hadoop 导出数据至关系型数据库。
-
Flume:分布式日志收集工具,用于实时采集、聚合和传输海量日志数据(如应用日志、访问日志),将数据输送至 HDFS/HBase。