一. 笔试部分
1. 怎么查看表结构,表创建语句?怎么查看表有哪些分区?怎么查看分区对应hdfs路径?怎么计算某个分区的数据量大小?
查看表结构
desc formatted table_name;
查看创建表语句
show create table table_name;
查看分区信息
show partitions table_name;
查看分区对应hdfs路径
desc formatted table_name partition (dt='20211218')
某个分区的数据量大小
hadoop fs -du /user/hive/warehouse/xxx.db/table_xx/xx_dt
2. 有一hive sql,怎么计算这个sql会产生多少个map数?(加面试追问)
切片大小默认是128m一个切片(具体看版本),开启一个maptask。
面试追问:Hadoop 默认块大小设置的依据是什么?为什么默认值设置为128M?这个128是怎么计算出来的?总不能是拍脑袋写的吧?
Math.max(minSize, Math.min(maxSize, blockSize))
minSize=1,blockSize=128M,maxSize=Long.MAX_VALUE
所以,默认情况,splitSize=blockSize=128M,其中:
minsize 通过mapreduce.input.fileinputformat.split.minsize参数控制
maxsize 通过mapreduce.input.fileinputformat.split.maxsize参数控制
面试继续追问:为什么之前版本是64M,现在默认是128M?
(1) HDFS中平均寻址时间大概为10ms;
(2) 经过测试发现,寻址时间为传输时间的1%时,为最佳状态;
所以最佳传输时间为10ms/0.01=1000ms=1s
(3) 目前磁盘的传输速率普遍为100MB/s ,
网卡普遍为千兆网卡传输速率普遍也是100MB/s;
计算出最佳block大小:100MB/s x 1s = 100MB
所以设定block大小为128MB。
(4) 实际在工业生产中,需要经过集群之间的具体情况进行设置。
比如: 跨物理机/机架之间文件传输速率为200MB/s时,一般设定block大小为256MB , 文件传输速率为400MB/s时,一般设定block大小为512MB . 不过最大一般不会超过512MB , 因为目前固态硬盘的读写速率应该不会超过512MB。
面试继续追问:hive on spark怎么考虑map数?
(1)Application:初始化一个SparkContext即生成一个Application;
(2)Job:一个Action算子就会生成一个Job;
(3)Stage:Stage等于宽依赖的个数加1;
(4)Task:一个Stage阶段中,最后一个RDD的分区个数就是Task的个数。
3. 怎么查看hive有什么自带函数?怎么查看函数的详细信息?
show functions;
desc function upper;
upper(str) - Returns str with all characters changed to uppercase
4. 请指出下面sql语句的区别?
select a.* from a left Join b on a.key = b.key and a.ds=xxx and b.ds=xxx
sclect a.* from a lef Join b on a.key = b.key and b.ds=xxx
select a.* from a lef Join b on a.key = b.key and b.ds=xxx where a.ds=xxx
Select a.* from a left Join b on a.key = b.key where a.ds=xxx and b.ds=xxx
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表。
on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
where条件是在临时表生成好后,再对临时表进行过滤的条件。条件不为真的就全部过滤掉。
5. 用sql算出res列,即同一个uid下,上一次is_succ=1 时的 id是多少?
id | time | uid | is_suc | res |
---|---|---|---|---|
1 | 2021-01-01 | 1 | 1 | Null |
2 | 2021-01-02 | 1 | 0 | 1 |
3 | 2021-01-03 | 1 | 0 | 1 |
4 | 2021-01-04 | 1 | 1 | 1 |
5 | 2021-01-05 | 1 | 0 | 4 |
6 | 2021-01-06 | 2 | 0 | Null |
7 | 2021-01-07 | 2 | 1 | Null |
8 | 2021-01-08 | 2 | 0 | 7 |
select id,`time`,uid,is_suc,res
from (
select a.id,a.`time`,a.uid,a.is_suc,b.id res,
row_number() over(partition by a.id order by b.id desc) rk
from test a
left join
(select uid,`time`,id from test where is_suc='1') b
on a.uid = b.uid and a.`time`>b.`time` ) c
where rk =1 order by 'time'
) d
6. 连续3周活跃用户,7天连续3天活跃用户数,写个思路
3周活跃用户
按照设备id对周活进行分组,统计次数大于3次。
如何分析最近七天内连续三天活跃用户数?
(1)查询出最近7天的活跃用户,并对用户活跃日期进行排名
(2)计算用户活跃日期及排名之间的差值
(3)对同用户及差值分组,统计差值个数
(4)将差值相同个数大于等于3的数据取出,然后去重,即为连续3天及以上活跃的用户
7. 一个list [1,5,5,7,9] 去重,并计算时间空间复杂度
时间复杂度是指执行算法所需要的计算工作量
空间复杂度是指执行这个算法所需要的内存空间
let list = [1,5,5,7,9];
function check(list) {
let obj = {};
for (let i = 0; i < list.length; i++) {
let item = list[i];
if (obj[item] != undefined) {
list[i] = list[list.length - 1];
list.length--;
i--;
}
obj[item] = item;
}
return list;
}
只通过一次for循环来判断对象中是否已经存在该值,所以就是 n 的复杂度,也就是 O(n)
8. 单链表的反转
就地反转法
public ListNode reverseList1(ListNode head) {
if (head == null)
return head;
ListNode new_node = new ListNode(-1);
new_node.next = head;
ListNode prev = new_node.next;
ListNode pcur = prev.next;
while (pcur != null) {
prev.next = pcur.next;
pcur.next = new_node.next;
new_node.next = pcur;
pcur = prev.next;
}
return new_node.next;
}
新建链表,头节点插入法
public ListNode reverseList2(ListNode head) {
ListNode new_node = new ListNode(-1);
ListNode pcur = head;
while (pcur != null) {
ListNode pNex = pcur.next;
pcur.next = new_node.next;
new_node.next = pcur;
pcur = pNex;
}
return new_node.next;
}
二. 技术面试部分
1. 我看你简历上有写到熟悉Hive原理和优化,你说一下怎么优化?
可以从以下方面说起。集体细节看以往文章。说出几个方面就行。
(1)小表、大表Join
(2)大表Join大表
(3)MapJoin
(4)开启Map端聚合
(5)笛卡尔积
(6)行列过滤
(7)合理设置Map及Reduce数
(8)并行执行
(9)JVM重用
(10)列式存储与压缩
2. 在Hive执行语句的时候如果很慢,什么原因造成?提到数据倾斜的问题,他又问怎么解决数据倾斜?
可从资源,引擎,数据倾斜,数据量等等方面去说。
追问数据倾斜,怎么解决
先回答
(1)数据预处理。
(2)解决热点数据:分而治之(第一次打散计算,第二次再最终聚合计算)
(3)导致最终只有一个Reduce任务的,需要想到用替代的关键字或者算子去提升Reduce任务数。
(4)调参。
然后细节
(1)group by配置调整
(2)join基础优化
(3)sort by代替order by
(4)单独处理倾斜key
具体细节参考以往文章。
3. 消费kafka数据会不会重复消费,什么情况下会重复消费?
从消息发送和消息消费两个方面去说。
ACK
0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据。
1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据。
-1:producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复。
消费
写入sink没有提交offset,下次消费还从处理过的offset消费。这个时候要么做到幂等不影响下游。要么就是事务+两阶段提交。
4. 你知道Spark的宽窄依赖吗? 任务是怎么切分的?
窄依赖是指父RDD的每个分区只被子RDD的一个分区所使用,子RDD分区通常对应常数个父RDD分区。
宽依赖是指父RDD的每个分区都可能被多个子RDD分区所使用,子RDD分区通常对应所有的父RDD分区。
(1)Application:初始化一个SparkContext即生成一个Application;
(2)Job:一个Action算子就会生成一个Job;
(3)Stage:Stage等于宽依赖的个数加1;
(4)Task:一个Stage阶段中,最后一个RDD的分区个数就是Task的个数。
5. 你们数仓用什么建模方法,说出常见的建模方法?
(1)范式建模法
从关系型数据库的角度出发,结合了业务系统的数据模型,能够比较方便的实现数据仓库的建模。然而,在某些时候反而限制了整个数据仓库模型的灵活性,性能等问题。
(2)维度建模法
维度建模非常直观,紧紧围绕着业务模型,可以直观的反映出业务模型中的业务问题。
(3)实体建模法
客观世界应该是可以细分的,客观世界应该可以分成由一个个实体,以及实体与实体之间的关系组成。
追问:维度建模
星型模型(一级维度表)
雪花(多级维度)
星座模型(星型模型+多个事实表)
追问:维度退化怎么理解
当一个维度没有数据仓库需要的任何数据时就可以退化此维度。需要把维度退化的相关数据迁移到事实表中,然后删除退化的维度。
维度属性也可以存储到事实表中,这种存储到事实表中的维度列被称为“维度退化”。与其他存储在维表中的维度一样 , 维度退化也可以用来进行事实表的过滤查询、实现聚合操作等。
6. 维度建模有什么好处? 为什么选择这个?
维度建模非常直观,紧紧围绕着业务模型,可以直观的反映出业务模型中的业务问题。不需要经过特别的抽象处理,即可以完成维度建模。
星型模式之被广泛使用,针对各个维度作了大量的预处理,如的统计、分类、排序等。通过这些预处理,提升数据仓库的处理能力。
7. 怎么判断一个需求能不能实现,你们的判断标准是什么?
一个需求实现,还与产品或者领导划定的交付时间有关系,还与现有的公司的技术,架构,和人才涉及技术方面有关系。
需求来了要讨论,怎么写,用什么技术,实现逻辑是什么,技术难点在哪。 拿到需求一般要开会,多人一起分析拆解需求,转变成一条条可实现的技术,如果出现了无法评估可行性的需求,就要去做技术调研,也就是查资料,问朋友,或者花钱买别人的代码/接口。
8. 挑一个比较有亮点的项目详细说
从 0 到 1 的项目,在这个项目中,数据仓库的建模,维度选择,数仓的分层等等,到最后指标开发都一路参与其中,从中了解到了数据的流转和整个数据仓库的生命周期。在这个项目中是一种质的飞跃。也主动承担了一些责任感的角色,去推动项目正常运行,保证了项目正常上线 . . . . . .
这个问题可以结合自己实际工作经验去说,自己也要准备好说辞去应对面试提问在项目中遇到的难点,最后怎么解决的;自身的优缺点等等这类主观性问题。