目录
- 1.数仓理论、建模理论了解多少? 星座模型知道吗?和星型模型有什么区别?
- 2.HDFS的常见数据类型
- 3.列存储和行存储的异同点,列存储有哪些优点
- 4.Hive都用过什么窗口函数?窗口函数如何取得当前行,如何取得前n行和后n行?
- 5.Hive数据倾斜什么表现,如何处理?
- 6.仔细说下如何调整MapTask和ReduceTask中内存大小和cpu核数;小文件如何处理?切片大小能不能任意调整?
- 7.知道UDF、UDTF、UDAF吗?他们有什么区别?自己写过这些函数吗
- 8.表名:log,字段:时间 dt、用户ID uid、城市 city、访问时间 tms;返回:一个时间内的某个城市的pv(次数)和uv(人数)
- 9.Flume都有哪些组件?分别使用什么类型的Source、Channel和Sink?
- 10.Kafka如何保证不丢数,如何保证不重复数据?
- 11.为什么用了Flume还要用Kafka?
1.数仓理论、建模理论了解多少? 星座模型知道吗?和星型模型有什么区别?
1.1数仓分层
1.2建模知识
关系建模和维度建模是两种数据仓库的建模技术。
1、关系建模(关系型数据库)
- 关系建模中,遵循的规则是范式,范式的作用是降低数据的冗余性。
- 关系建模将复杂的数据抽象为两个概念:实体和关系,严格遵循三范式,数据冗余程度低,一致性会得到保证。表现为松散、零碎、物理表数量多,查询会相对复杂,大数据场景下,查询效率较低
2.函数依赖
- 完全函数依赖
- 非主键属性部分依赖于主键
- 非主键属性传递依赖于主键
3.维度建模
- 以数据分析作为出发点,不遵循三范式,因此数据存在一定的冗余,维度模型面向业务,将业务用事实表和维度表呈现出来。表结构简单,查询简单,查询效率高。
1.3维度表和事实表
1.维度表:对业务事实的描述信息,每张维度表对应现实世界中的一个对象或者概念。例如:用户、商品、日期、地区等。
- 维度的范围很宽,属性多,列多
- 跟事实表相比,行数相对较小
- 内容相对固定
2.事实表:每行数据代表一个业务事件(下单、支付、退款、评价等)
- 非常的大,行数多
- 内容相对窄,字段,列比较少(字段包括两大类:外键id和数值型的度量值)
- 经常发生变化,每天会新增很多
3.事实表的分类
- 事务型事实表:以每个事务或事件为单位,比如一个销售订单记录,一笔支付记录,作为事实表里的一行数据,一旦事务被提交,事实数据表被插入,数据就不再进行更改,更新方式为增量更新。
- 周期型快照事实表:不会保留所有数据,只保留固定时间间隔的数据,比如购物车,只保留每天结束时用户购物车里有什么商品
- 累积型快照事实表:用于跟踪业务事务的变化,新增及变化同步
1.4维度模型的分类
1.星型模型
- 两者区别在于维度的层级,标准的星型模型维度只有一层,而雪花模型可能会涉及多层
2.雪花模型
- 会对维度表进行规范化,消除冗余,但是无法完全遵循三范式
3.星座模型
- 区别在于事实表的数量,星座模型中多个事实表可能会共用一个维度表
4.如何进行模型的选择
- 星型模型,没有进行规范化,因此性能最好;雪花模型的维度表进行了一些规范化,因此比较灵活
- 倾向于维度更少的星型模型,因为在hadoop体系下,减少join操作,也就是减少shuffle。
1.5数据仓库如何建模
1.ODS层,保存原始数据不做任何处理,共存储两类数据:业务数据(mysql)和用户行为日志(日志服务器文件格式)
- 用户行为日志,存储在日志服务器上;一个日志就是一张表,一张表有一个string类型的字段,一行就是一条日志,按天分区,每个分区中存储用户当天产生的行为日志
- 业务数据,使用sqoop从关系型数据库mysql中同步到HDFS上,每张表对应HDFS上的一个文件,参照mysql同步了哪些表,就建立那些表;表的结构:每行数据和字段同步于mysql中的表结构;分区:按天分区,每天的分区存储当天从关系型数据库同步的数据。
2.DIM层和DWD层
- DWD中存放的是业务事实,存放的事实表
- DIM中存放的是对业务事实的描述信息,存放的是维度表
3.DWS和DWT层
- 目的是为了避免重复计算
维度建模的过程
- 1.选择业务过程:确定建立哪些事实表。 在业务系统中,挑选业务线,比如下单业务、支付业务、退款业务、物流业务,一条业务线对应一张事实表。
- 2.声明粒度:确定事实表中的一行数据表示什么,应该选择最小粒度。 指数据仓库的数据中保存数据的细化程度或综合程度的级别。(数据越明细,粒度越小,数据越汇总,粒度越大)。
- 3.确定维度:与每张事实表相关的维度有哪些。确定每张事实表中的维度外键有哪些
- 4.确认事实:确定每张事实表中的度量值
2.HDFS的常见数据类型
- Text文本类型
- IntWritable 整数型
- LongWritable 长整数型
- BooleanWritable 布尔型
- FloatWritable 浮点型
3.列存储和行存储的异同点,列存储有哪些优点
3.1异同点
- 相同:
- 不同:
(1)传统行式数据库的特性: - 数据按照行存储
- 如果没有索引的查询要使用大量的IO,一般的数据库都会建立索引,通过索引加快查询效率
- 建立索引和物化视图需要花费大量的时间和资源
- 面对查询需求,数据库必须被大量膨胀才能满足需求
(2)列式数据库
- 数据按列存储,每一列单独存放
- 数据即索引
- 只访问查询涉及的列,可以大量降低系统的IO
- 每一列由一个线程处理,即查询的并罚处理性能高
- 数据类型一致,数据特征相似,可以高效压缩,有利于存储和网络输出数据带宽的消耗。
(3)
- 行式存储倾向于结构固定,列式存储倾向于结构弱化
- 行式存储存储一行数据仅需要一个主键,列式存储存储一行数据需要多份主键
- 列式存储存储的都是业务数据,而列式存储除了业务数据之外,还需要存储列名。
- 行式存储像是一个java bean,所有的字段都提前定义好;列式存储更像是一个map,不提前定义,随意往里面加key/value。
3.2列存储的优点
- 每个字段的数据聚集存储,在查询只需要几个字段的时候,能大大减少读取的数据量
- 每个字段的数据类型是相同的,列式存储可以针对性的设计更好的设计压缩算法
4.Hive都用过什么窗口函数?窗口函数如何取得当前行,如何取得前n行和后n行?
- rank()、dense_rank()、row_number()
- lag(col,n,默认值),如果没给默认值则第一行为null,往前第n行数据
- lead(col,n,默认值),往后第n行数据,后面都要接over()才可以
当前行
- rows between 1 preceding and 1 following 当前行和前面一行及后面一行
- rows between 1 preceding and current row 当前行和前面一行
- rows between current row and 1 following 当前行和后面一行
- sum() over() 所有行相加
- sum() over(partition by name) 按name分组,组内数据相加
- sum() over(partition by name order by orderdate) 按name分组,组内数据累积相加
- sum() over(partition by name order by orderdate rows between unbounded preceding and current row) 按name分组,组内由起点行到当前数据的累加
- sum() over(partition by name order by orderdate rows between current row and unbounded following)
lag和lead的用法
- select orderdata,lag(orderdate,1,orderdate) as t1 from table 当前时间和上一次时间,如果没有上一次时间,则为orderdate本身
4.1表table1(usr_id int,usr_dt string),其中id字段数值相同,找出表中连续活跃的天数,如果不连续,则当前行连续活跃字段设为1,返回查询结果table2(窗口函数)
4.2如何将表table1的usr_dt字段的值转化成一个字符串,以逗号分隔(concat_ws()和collect_set()函数的使用)
4.3如何将表table3的中生成的那个字符串变成原先table1的形式(UDTF中的explode()和lateral view()函数的使用)
5.Hive数据倾斜什么表现,如何处理?
- 任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)子任务未完成。
6.仔细说下如何调整MapTask和ReduceTask中内存大小和cpu核数;小文件如何处理?切片大小能不能任意调整?
- mapreduce.map.memory.mb :默认是1024M,根据128m对应1g内存提高该内存
- mapreduce.map.cpu.vcores:默认cpu是1,可以增加cpu核数
- mapreduce.reduce.memory.mb:默认是1024m,可提高
- mapreduce.reduce.cpu.vcores:默认是1个,可增加
小文件处理
- 1.在数据采集的时候,将小文件合成大文件再上传
- 2.存储方向Hadoop Archive,高效的将小文件放入HDFS中的文件存档工具,打包成一个har文件,减少namenode的内存使用
- 3.计算方向CombineInputFormat,将小文件在切片中生成一个单独的切片或者少量的切片
- 4.开启uber,实现jvm重用,让同一个job的多个task运行在一个jvm上,不必为每个task都开启一个jvm。
7.知道UDF、UDTF、UDAF吗?他们有什么区别?自己写过这些函数吗
- UDF:一进一出 concat
- UDAF:聚集函数,多进一出,聚集函数count,sum
- UDTF:一进多出 explode炸裂函数
- concat_ws(分隔符,str1,str2)
select concat_ws(',',xingzuo,xuexing) as t1 from table
把星座和血型用逗号连接到一个字段中- collect_set(col)……group by() ,与group by连用,将某字段的值进行去重汇总,产生数组类型字段
select concat_ws('|',collect_set(name) from table group by m
按照m分组,将name去重之后,再通过|连接起来- split(string,’,’) 将字符串string拆成一个数组
- explode(col) 将一列中的数组拆分成多行
select c1 from table lateral view explode(split(ca,",")) table2 as c1;
把ca这一列的字符串先split成数组,然后explode炸裂成多行形成侧写表table2,新的列名为c1
8.表名:log,字段:时间 dt、用户ID uid、城市 city、访问时间 tms;返回:一个时间内的某个城市的pv(次数)和uv(人数)
8.1group by子句中,有两个字段,这个过程会触发几个MR过程?
8.2.count(*)和count(uid)有啥不同?和count(1)有何不同?
- count(*) 查询的是所有的行
- count(uid) 会去除null
- count(1)和count(*)结果一样,
- 效率:count(*)=count(1)>count(id)>count(字段)
- 列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count(*)最优。