当前位置: 首页 > article >正文

快手数仓面试题附答案

题目

  • 1 讲一下你门公司的大数据项目架构?
  • 2 你在工作中都负责哪一部分
  • 3 spark提交一个程序的整体执行流程
  • 4 spark常用算子列几个,6到8个吧
  • 5 transformation跟action算子的区别
  • 6 map和flatmap算子的区别
  • 7 自定义udf,udtf,udaf讲一下这几个函数的区别,编写的时候要继承什么类,实现什么方法
  • 8 hive创建一个临时表有哪些方法
  • 9 讲一下三范式,三范式解决了什么问题,有什么优缺点
  • 10 讲一下纬度建模的过程 
  • 11 纬度表有哪几种
  • 12 事实表有几种
  • 13 什么是纬度一致性,总线架构,事实一致性
  • 15 什么是拉链表,如何实现?
  • 16 什么是微型纬度、支架表,什么时候会用到
  • 17 讲几个你工作中常用的spark 或者hive 的参数,以及这些参数做什么用的
  • 18 工作中遇到数据倾斜处理过吗?是怎么处理的,针对你刚刚提的方案讲一下具体怎么实现。用代码实现,以及用sql实现。
  • 19 讲一下kafka对接flume 有几种方式。
  • 20 讲一下spark是如何将一个sql翻译成代码执行的,里面的原理介绍一下?
  • 21 spark 程序里面的count distinct 具体是如何执行的
  • 22 不想用spark的默认分区,怎么办?(自定义Partitioner 实现里面要求的方法 )具体是哪几个方法?
  • 23 有这样一个需求,统计一个用户的已经曝光了某一个页面,想追根溯是从哪几个页面过来的,然后求出在这几个来源所占的比例。你要怎么建模处理?
  • 23 说一下你对元数据的理解,哪些数据算是元数据
  • 24 有过数据治理的经验吗?
  • 25 说一下你门公司的数据是怎么分层处理的,每一层都解决了什么问题
  • 26 讲一下星型模型和雪花模型的区别,以及应用场景

答案

1 讲一下你门公司的大数据项目架构?

实时流和离线计算两条线
数仓输入(客户端日志,服务端日志,数据库)
传输过程(flume,kafka)
数仓输出(报表,画像,推荐等)
2 你在工作中都负责哪一部分
3 spark提交一个程序的整体执行流程
包括向yarn申请资源、DAG切割、TaskScheduler、执行task等过程

4 spark常用算子列几个,6到8个吧

常用的RDD转换算子:

  1. filter(func) 筛选出满足函数func的元素,并返回一个新的数据集
  2. map(func) 将每个元素传递到函数func中,并将结果返回为一个新的数据集
  3. flatMap(func) 与map()相似,但每个输入元素都可以映射到0或多个输出结果
  4. groupByKey() 应用于(K,V)键值对的数据集时,返回一个新的(K, Iterable)形式的数据集
  5. reduceByKey(func) 应用于(K,V)键值对的数据集时,返回一个新的(K, V)形式的数据集,其中每个值是将每个key传递到函数func中进行聚合后的结果

行动操作常用算子:

  1. count() 返回数据集中的元素个数
  2. collect() 以数组的形式返回数据集中的所有元素
  3. first() 返回数据集中的第一个元素
  4. take(n) 以数组的形式返回数据集中的前n个元素
  5. reduce(func) 通过函数func(输入两个参数并返回一个值)聚合数据集中的元素
  6. foreach(func) 将数据集中的每个元素传递到函数func中运行

5 transformation跟action算子的区别

所有的transformation都是采用的懒策略,就是如果只是将transformation提交是不会执行计算的,计算只有在action被提交的时候才被触发。

  • Transformation 变换/转换:这种变换并不触发提交作业,完成作业中间过程处理。Transformation 操作是延迟计算的,也就是说从一个RDD 转换生成另一个 RDD 的转换操作不是马上执行,需要等到有 Action 操作的时候才会真正触发运算。
  • Action 行动算子:这类算子会触发 SparkContext 提交 Job 作业。
    Action 算子会触发 Spark 提交作业(Job)。

transformation操作:

  1. map(func):对调用map的RDD数据集中的每个element都使用func,然后返回一个新的RDD,这个返回的数据集是分布式的数据集
  2. filter(func): 对调用filter的RDD数据集中的每个元素都使用func,然后返回一个包含使func为true的元素构成的RDD
  3. flatMap(func):和map差不多,但是flatMap生成的是多个结果
  4. mapPartitions(func):和map很像,但是map是每个element,而mapPartitions是每个partition
  5. mapPartitionsWithSplit(func):和mapPartitions很像,但是func作用的是其中一个split上,所以func中应该有index
  6. sample(withReplacement,faction,seed):抽样
  7. union(otherDataset):返回一个新的dataset,包含源dataset和给定dataset的元素的集合
  8. distinct([numTasks]):返回一个新的dataset,这个dataset含有的是源dataset中的distinct的element
  9. groupByKey(numTasks):返回(K,Seq[V]),也就是hadoop中reduce函数接受的key-valuelist
  10. reduceByKey(func,[numTasks]):就是用一个给定的reducefunc再作用在groupByKey产生的(K,Seq[V]),比如求和,求平均数
  11. sortByKey([ascending],[numTasks]):按照key来进行排序,是升序还是降序,ascending是boolean类型
  12. join(otherDataset,[numTasks]):当有两个KV的dataset(K,V)和(K,W),返回的是(K,(V,W))的dataset,numTasks为并发的任务数
  13. cogroup(otherDataset,[numTasks]):当有两个KV的dataset(K,V)和(K,W),返回的是(K,Seq[V],Seq[W])的dataset,numTasks为并发的任务数
  14. cartesian(otherDataset):笛卡尔积就是m*n,大家懂的

action操作:

  1. reduce(func):说白了就是聚集,但是传入的函数是两个参数输入返回一个值,这个函数必须是满足交换律和结合律的
  2. collect():一般在filter或者足够小的结果的时候,再用collect封装返回一个数组
  3. count():返回的是dataset中的element的个数
  4. first():返回的是dataset中的第一个元素
  5. take(n):返回前n个elements,这个士driverprogram返回的
  6. takeSample(withReplacement,num,seed):抽样返回一个dataset中的num个元素,随机种子seed
  7. saveAsTextFile(path):把dataset写到一个textfile中,或者hdfs,或者hdfs支持的文件系统中,spark把每条记录都转换为一行记录,然后写到file中
  8. saveAsSequenceFile(path):只能用在key-value对上,然后生成SequenceFile写到本地或者hadoop文件系统
  9. countByKey():返回的是key对应的个数的一个map,作用于一个RDD
  10. foreach(func):对dataset中的每个元素都使用func

参考:Spark常用算子详解_spark算子-CSDN博客


6 map和flatMap算子的区别

  • map:执行完map后会得到一个新的分布式数据集,数据集中每个元素是之前的RDD映射得来的,与之前RDD每个元素存在一一对应的关系。
  • flatmap:而flatmap有一点不同,每个输入的元素可以被映射为0个或者多个输出的元素,原RDD与新RDD的元素是一对多的关系。当然光看定义比较抽象,下面用一个图说明,

参考:Spark之Map VS FlatMap - 知乎


7 自定义udf,udtf,udaf讲一下这几个函数的区别,编写的时候要继承什么类,实现什么方法

区别:

  • UDF:输入一行,输出一行
    UDF:用户定义(普通)函数,只对单行数值产生作用;
  • UDTF:输入一行,输出多行,类似explode函数
    UDTF:User-Defined Table-Generating Functions,用户定义表生成函数,用来解决输入一行输出多行;
  • UDAF:输入多行,输出一行,类似聚合函数
    UDAF:User- Defined Aggregation Funcation;用户定义聚合函数,可对多行数据产生作用;等同与SQL中常用的SUM(),AVG(),也是聚合函数;

Hive实现:

类型方法
UDF

类:

GenericUDF


包路径:
org.apache.hadoop.hive.ql.udf.generic

initialize:类型检查,返回结果类型
入参:ObjectInspector[]
出参:ObjectInspector
 

evaluate:功能逻辑实现

入参:DeferredObject[]

出参:Object

getDisplayString:函数名称
入参:String[]

出参:String
 

close:关闭函数,释放资源等
入参:无

出参:void

UDTF

类:
GenericUDTF

包路径:
org.apache.hadoop.hive.ql.udf.generic

initialize:类型检查,返回结果类型
入参:StructObjectInspector
出参:StructObjectInspector

process:功能逻辑实现
**调用forward输出一行数据,可多次调用

入参:Object[]

出参:void

close:关闭函数,释放资源等
入参:无

出参:void

UDAF

类:
AbstractGenericUDAFResolver

包路径:
org.apache.hadoop.hive.ql.udf.generic

类:
GenericUDAFEvaluator

包路径:
org.apache.hadoop.hive.ql.udf.generic
 


类:

AbstractAggregationBuffer

包路径:
org.apache.hadoop.hive.ql.udf.generic

-----AbstractGenericUDAFResolver-----

getEvaluator:获取计算器
入参:TypeInfo[]
出参:GenericUDAFEvaluator

---------GenericUDAFEvaluator----------

init:
入参:Mode,ObjectInspector[]
出参:ObjectInspector

getNewAggregationBuffer:

入参:无

出参:AggregationBuffer

reset:

入参:AggregationBuffer

出参:void

iterate:

入参:AggregationBuffer,Object[]

出参:void

merge:

入参:AggregationBuffer,Object

出参:void


terminate:

入参:AggregationBuffer

出参:Object

terminatePartial:

入参:AggregationBuffer

出参:Object

--------AbstractAggregationBuffer-------
estimate:评估内存占用大小

入参:无

出参:int

UDAF说明

  • 一个Buffer作为中间处理数据的缓冲:获取getNewAggregationBuffer、重置reset
  • 四个阶段(Mode):
    1. PARTIAL1(Map阶段):
      from original data to partial aggregation data:
      iterate() and terminatePartial() will be called.
    2. PARTIAL2(Map的Combiner阶段):
      from partial aggregation data to partial aggregation data:
      merge() and terminatePartial() will be called.
    3. FINAL(Reduce 阶段):
      from partial aggregation to full aggregation:
      merge() and terminate() will be called.
    4. COMPLETE(Map Only阶段):
      from original data directly to full aggregation:
      iterate() and terminate() will be called.
  • 五个方法:
    1. 初始化init
    2. 遍历iterate:PARTIAL1和COMPLETE阶段
    3. 合并merge:PARTIAL2和FINAL阶段
    4. 终止terminatePartial:PARTIAL1和PARTIAL2阶段
    5. terminate:COMPLETE和FINAL阶段

Spark实现:

参考:Spark - 自定义函数(UDF、UDAF、UDTF) - 知乎

8 hive创建一个临时表有哪些方法

WITH创建临时表

如果这个临时表并不需要保存,并且下文只需要用有限的几次,我们可以采用下面的方法。

with as 也叫做子查询部分,首先定义一个sql片段,该sql片段会被整个sql语句所用到,为了让sql语句的可读性更高些,作为提供数据的部分,也常常用在union等集合操作中。

with as就类似于一个视图或临时表,可以用来存储一部分的sql语句作为别名,不同的是with as 属于一次性的,而且必须要和其他sql一起使用才可以!

其最大的好处就是适当的提高代码可读性,而且如果with子句在后面要多次使用到,这可以大大的简化SQL;更重要的是:一次分析,多次使用,这也是为什么会提供性能的地方,达到了“少读”的目标。

WITH t1 AS (
        SELECT *
        FROM a
    ), 
    t2 AS (
        SELECT *
        FROM b
    )
SELECT *
FROM t1
JOIN t2
;

注意:

  • 这里必须要整体作为一条sql查询,即with as语句后不能加分号,不然会报错。
  • with子句必须在引用的select语句之前定义,同级with关键字只能使用一次,多个只能用逗号分割
  • 如果定义了with子句,但其后没有跟select查询,则会报错!
  • 前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能嵌套with子句!

Temporary创建临时表

create temporary table 临时表表名 as 
select * from 表名
  • 创建的临时表仅仅在当前会话可见,数据会被暂存到hdfs上,退出当前会话表和数据将会被删除。数据将存储在用户的scratch目录中,并在会话结束时删除。
  • 从Hive1.1开始临时表可以存储在内存或SSD,使用hive.exec.temporary.table.storage参数进行配置,该参数有三种取值:memory、ssd、default。
    如果内存足够大,将中间数据一直存储在内存,可以大大提升计算性能。

  • 如果临时表的命名的表名和hive的表名一样,当前会话则会查询临时表的数据,用户在这个会话内将不能使用原表,除非删除或者重命名临时表
  • 临时表不支持分区字段,不支持创建索引。

参考:大数据开发之Hive篇7-Hive临时表 - 知乎

9 讲一下三范式,三范式解决了什么问题,有什么优缺点

三范式:

  • 第一范式:列的原子性,字段值不可再分,比如某个字段的取值是姓名+手机号,那就要把姓名和手机号分成两个字段
  • 第二范式:第一范式的基础上,非主键列不能依赖主键的一部分,例如字段a和字段b组成的主键,某个字段只依赖a,就需要把这个字段剥离到a对应的表
  • 第三范式:第二范式的基础上,非主键列不能传递依赖主键,例如字段c依赖字段b,字段b依赖主键字段a,那么就可以把这个字段c剥离到字段b为主键的表

三范式是要解决字段冗余,节省存储空间,数据维护更方便,不需要多处更新同样的字段;

缺点是不方便查询,要进行多表join效率低,不适合分析类的查询。

范式化设计的优点:可以减少数据冗余,数据表体积小更新快,范式化的更新操作比 反范式化更快,范式化的表通常比反范式化更小。
缺点:对于查询需要对多个表,会关联多个表,在应用中,进行表关联的成本是很高
更难进行索引优化


反范式化设计的优点:可以减少表的关联,可以对查询更好的进行索引优化,
缺点:表结构存在数据冗余和数据维护异常,对数据的修改需要更多资源。

因此在设计数据库结构的时候要将反范式化和范式化结合起来

参考:你了解数据库三大范式吗?用来解决什么问题?_数据库三范式解决了什么问题_我是等闲之辈的博客-CSDN博客mysql--数据库优化的目的、数据库设计的步骤以及什么是三范式、三范式的优缺点-CSDN博客


10 讲一下纬度建模的过程

(选择业务过程 确定粒度 确定纬度 确定事实表)


11 纬度表有哪几种


12 事实表有几种


13 什么是纬度一致性,总线架构,事实一致性


15 什么是拉链表,如何实现?


16 什么是微型纬度、支架表,什么时候会用到


17 讲几个你工作中常用的spark 或者hive 的参数,以及这些参数做什么用的
18 工作中遇到数据倾斜处理过吗?是怎么处理的,针对你刚刚提的方案讲一下具体怎么实现。用代码实现,以及用sql实现。


19 讲一下kafka对接flume 有几种方式

三种:source、channel、sink

source和sink对接方式:Flume对接Kafka详细过程_flume kafka_杨哥学编程的博客-CSDN博客

channel对接方式:flume--KafkaChannel的使用_kafka channel为什么没有sink-CSDN博客

20 讲一下spark是如何将一个sql翻译成代码执行的,里面的原理介绍一下?

SparkSQL主要是通过Catalyst优化器,将SQL翻译成最终的RDD算子的

阶段产物执行主体
解析Unresolved Logical Plan(未解析的逻辑计划)sqlParser
分析Resolved Logical Plan(解析的逻辑计划)Analyzer
优化Optimized Logical Plan(优化后的逻辑计划)Optimizer
转换Physical Plan(物理计划)Query Planner

        无论是使用 SQL语句还是直接使用 DataFrame 或者 DataSet 算子,都会经过Catalyst一系列的分析和优化,最终转换成高效的RDD的操作,主要流程如下:

        1. sqlParser 解析 SQL,生成 Unresolved Logical Plan(未解析的逻辑计划)
        2. 由 Analyzer 结合 Catalog 信息生成 Resolved Logical Plan(解析的逻辑计划)
        3. Optimizer根据预先定义好的规则(RBO),对 Resolved Logical Plan 进行优化并生成 Optimized Logical Plan(优化后的逻辑计划)
        4. Query Planner 将 Optimized Logical Plan 转换成多个 Physical Plan(物理计划)。然后由CBO 根据 Cost Model 算出每个 Physical Plan 的代价并选取代价最小的 Physical Plan 作为最终的 Physical Plan(最终执行的物理计划)
        5. Spark运行物理计划,先是对物理计划再进行进一步的优化,最终映射到RDD的操作上,和Spark Core一样,以DAG图的方式执行SQL语句。 在最新的Spark3.0版本中,还增加了Adaptive Query Execution功能,会根据运行时信息动态调整执行计划从而得到更高的执行效率

        整体的流程图如下所示:

参考:SparkSQL运行流程浅析_简述spark sql的工作流程-CSDN博客


21 spark 程序里面的count distinct 具体是如何执行的

  • 一般对count distinct优化就是先group by然后再count,变成两个mapreduce过程,先去重再count。

  • spark类似,会发生两次shuffle,产生3个stage,经过4个步骤:①先map端去重,②然后再shuffle到reduce端去重,③然后通过map做一次partial_count,④最后shuffle到一个reduce加总。

  • spark中多维count distinct,会发生数据膨胀问题,会把所有需要 count distinct 的N个key组合成List,行数就翻了N倍,这时最好分开来降低单个任务的数据量。

参考:大数据SQL COUNT DISTINCT实现原理 - 知乎


22 不想用spark的默认分区,怎么办?(自定义Partitioner 实现里面要求的方法 )具体是哪几个方法?

abstract class Partitioner extends Serializable {
  def numPartitions: Int
  def getPartition(key: Any): Int
}

参考:Spark自定义分区器-CSDN博客 

23 有这样一个需求,统计一个用户的已经曝光了某一个页面,想追根溯是从哪几个页面过来的,然后求出在这几个来源所占的比例。你要怎么建模处理?(这里回答的不好,挺折磨的。面试官的意思是将所有埋点按时间顺序存在一个List 里,然后可能需要自定义udf函数,更主要的是考虑一些异常情况,比如点击流中间是断开的,或者点击流不全,怎么应对)
23 说一下你对元数据的理解,哪些数据算是元数据
24 有过数据治理的经验吗?
25 说一下你门公司的数据是怎么分层处理的,每一层都解决了什么问题
26 讲一下星型模型和雪花模型的区别,以及应用场景


http://www.kler.cn/news/159670.html

相关文章:

  • 流量异常-挂马造成百度收录异常关键词之解决方案(虚拟主机)
  • python内存处理和常见的内存泄漏场景
  • 【从删库到跑路 | MySQL数据库总结篇】JDBC编程
  • 【论文】F1的单位是%还是1,mAP的单位是%还是1?答:F1的单位是1,mAP的单位是%
  • flutter的CircularProgressIndicator基本使用
  • 【UGUI】实现背包的常用操作
  • USTC Fall2023 高级人工智能期末考试回忆版
  • 力扣:196. 删除重复的电子邮箱(Python3)
  • go第三方包发布(短精细)
  • InnoDB存储引擎体系结构中的各个组件是如何协同工作的?
  • WVP-RPO开源项目搭建实践
  • 苹果TF签名全称TestFlight签名,需要怎么做才可以上架呢?
  • C++笔试题之回文数的判断
  • 【Redis6快速深入学习04】Redis字符串(String)的使用和原理
  • 【分布式微服务专题】从单体到分布式(一、SpringCloud项目初步升级)
  • FAQ:Reference篇
  • Android各版本引入的重要安全机制介绍
  • nodeJS爬虫-爬取虎嗅新闻
  • vos3000怎样设置落地的优先级
  • HXDSP2441-I2C(Inter-Integrated Circuit)
  • 麒麟系统图形化应用自启
  • 【微信小程序开发】学习小程序的模块化开发(自定义组件和分包加载)
  • MinIo 的操作与使用和避坑
  • Mysql行格式(记录格式)详解
  • Leetcode—2477.到达首都的最少油耗【中等】
  • 《PFL》论文阅读笔记
  • Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
  • 基本数据类型与引用数据类型的区别(java基础)
  • 【软件测试】技术精选:Jmeter常见的几种报错
  • 云HIS:新一代云架构医院信息管理系统源码(java语言)