面试题

1.DataNode在什么情况下不会备份

单节点情况不会备份   或者设置副本数为1
 

2.hdfs的datanode的添加和删除需要执行的命令

添加:
hdaoop-daemon.sh start datanode 
hadoop-daemon.sh start tasktracker

删除:
hadoop maradmin -refreshnodes
hadoop dfsadmin -refreshnodes

重启namenode
hdaoop-daemon.sh start namenode

HDFS集群状态报告查看
hadoop dfsadmin -report

3.maptask和reducedtask的并行度

一个逻辑切片调用一次mapper类,逻辑切片和文件块对应。
所以maptask的并行度 = 文件块数量
 
reducetask的并行度 = 指定的reducetask数量   --> job.setNumReducetasks(7)
 

4.逻辑切片和文件块

逻辑切片是针对mapreduce执行时读取的单位
 
文件块是hdfs存储的单位
 
一个逻辑切片的大小等于文件块的大小:切片公式:Math.max(minSize, Math.min(maxSize, blockSize))
 
逻辑切片最后一片有1.1的最大值说法,文件块不存在这个概念
eg:266的文件
分为3个文件块,2个逻辑切片  因为最后一个逻辑切片大小为138<128*1.1,所以138不进行切分
 

5.yarn的调度器种类

fifo - 先进先出
fair - 公平调度器,所有job平分资源
capacity - 根据计算能力分配,需要手动配置资源占比
 

6.yarn提供资源的最小单位

container-容器-是一个逻辑概念,并没有将资源真正划分
一个container 封装了一定数量的内存,io,cpu,网络等资源
 
1个maptask/reducetask-----1个container
 

7.用mapreduce怎么处理数据倾斜

自己实现partition类,用key和value相加取hash值:
public class HashPartitioner<K, V> extends Partitioner<K, V> {
    private int aa= 0;
    /** Use {@link Object#hashCode()} to partition. */
    public int getPartition(K key, V value,int numReduceTasks) 
    {
        return (key.hashCode()+(aa++) & Integer.MAX_VALUE) % numReduceTasks;
    }
}

8.推测执行

数据倾斜时,某个key对应的分组很庞大,会执行很慢,开启推测执行后,会启动两个一样的task,那个先执行完,就杀死另一个。
 

9.hadoop如何杀死一个job

hadoop job -list   查看所有jobid
 
hadoop job -kill jobid  杀死job
 

10.分区表和分桶表

分区表的表现形式是表现在表结构上,分区表的分区字段存储在表的树目录结构上,分区字段称之为伪列
 
分桶表的表现形式是表现在表数据上,按照指定的分桶个数对分桶字段进行hash,数据进入指定的hash后的桶表里面。
 
分桶表原理:分桶字段%分桶数
 
分桶字段 age  桶中排序字段 dept
create table if not exists stu_buk(id int , name string ,  age int , dept string) 
clustered by (age) sorted by (dept desc) into 3 buckets 
row format delimited
fields terminated by ',';
 

11.hdfs的client端复制到第三个副本时宕机,hdfs怎么恢复保证下次写第三个副本

在第三个副本宕机时,会上报block块的信息给namenode,下次恢复就知道从哪个节点那个副本开始恢复
 

12.row_number和rank的区别

row_number:按查出的记录数前后排序,序号不重复,同一窗口,相同值,不同序
 
rank:跳跃排序,同一窗口,相同值,同序,后面间隔   总数和rn一致
 
dense_rank:同一窗口,相同值,同序,后面不间隔  总数会变少
 

13.sql关键字的执行顺序

from - join - on - where - group by - having - select - order by - limit 
 

14.缓慢变化维的处理

第一种方法,直接在原来维度的基础上进行更新,不会产生新的记录,这样不好回溯数据
第二种方法,不修改原有的数据,重新产生一条新的记录,这样就可以追溯所有的历史记录,相当于做一个拉链表
第三种方法,直接在原来维度的基础上进行更新,不会产生新的记录但是只会记录上一次的历史记录,这个最常用
 

15.表的分类

实体表 - 描述具体的对象,如员工,学生,商品
维度表 - 也可称之为码表,一般对应一些业务状态,如交易状态,订单状态,审批状态
事务型事实表 - 一旦产生不发生变化,如交易流水,操作日志,出入库记录
周期型事实表 - 随着业务发生不断产生数据,如订单,审批单等
 

16.维度建模和关系建模

实体-关系建模是面向应用,遵循第三范式,以消除数据冗余为目标的设计技术。
维度建模是面向分析,为了提高查询性能可以增加数据冗余,反规范化的设计技术。
 
关系模型 - 在关系型数据库使用,适用于OLTP,应用第三范式,减少不于主键直接关联的字段,减少数据冗余。
 
维度模型 - 在大数据中使用,适用OLAP,在大规模数据中,跨表分析统计查询过程会造成多表关联,这会大大降低执行效率
 
在维度建模的基础上分为:星型模型和雪花模型
 

17.mapreduce的运算发放

mapreduce的运算会随机发放到集群的所有节点。
 

18.拉链表的处理

1.将拉链表和最新的数据进行left  join ,找出需要处理字段发生变化的记录,更新原来start_time(今天)和end_time(昨天)
2.上面发生变化的记录插入一条最新数据,start_time为今天,end_time为2999-12-31
3.将最新的数据和拉链表进行left join,找出新增的记录,start_time为今天,end_time为2999-12-31
 

19.建模理论

维度建模:按照事实表,维度表来构建数据仓库,数据集市。
 
星型模型:维度表和事实表直接关联。
 
雪花模型:对星型模型的扩展,每个维表可以有子维表。
 

20.数仓如何保障数据准确性

1.在每一层处理前和处理后进行关键指标的校验
2.同历史数据进行对比,看是否数据量激增或折半
3.让业务进行数据核对
 

21.增量表和全量表

增量表:只上报当天发生变化的数据
 
全量表:合并截至当天的所有数据
 

22.数据库三个范式

数据库设计三大范式:
1NF : 所有的域都应该是原子性的。  ->字段不可分割
2NF : 所有的非主键字段必须与主键字段相关,不能与主键的部分相关(联合主键)。  ->一张表里面描述一类事物
3NF : 非主键字段必须与主键直接相关,而不能间接相关。    ->非主键字段不能直接相关,减少无用字段
 
数仓理论
 
数仓具体实现
 
23.数仓建模的每个层级及作用
 
24.数据质量校验
如何验证数仓层和报表层的数据质量?
 
 

25.sql优化

1.避免全表扫描,在where和order by 涉及的列建立索引
2.避免在where进行null 的判断,可用‘’ 0等代替空值,避免进行 != <> 不等判断,or连接条件
3.避免在where上对列进行算术运算或者函数操作
4.能用join的话就不要使用子查询
 

26.元数据管理和数据生命周期

 

27.数据去重方案

每小时去重
每天23点将一天数据进行去重
 

28.sql里面的排序函数

 

 

29.行转列,列转行

 
 

30.udf

 

31.数据仓库规范的定制

1.库名,表名,字段名的命名规范   下划线法命名   
2.分区字段的规定  日期,小时 
3.存储位置的规定  同业务放一个hdfs大目录
4.存储格式的规定  orc
5.表注释的规定    
 

32.数据量

dwd层大业务宽表:1小时10G 一天250G
dwd层明细表:1小时4G  一天100G
ods层分上报渠道:互联网一小时50G   app一小时70G
 

33.数仓中数据的抽取方式

增量抽取:捕获变化数据,仅对自上次导出之后变化数据(增、删、改)进行抽取。对捕获方法有两点           要求----1:准确    
                 2:不要对业务系统造成太大压力
全量抽取:将数据源中的表或视图原封不动的从数据库中抽取到目标系统。
 

34.天表和小时表的数据同步

小时表示全量同步
天全量表的话,拿最新一天的数据和昨天的全量数据进行对比,增量同步。
 
 

35.NameNode在启动的时候会做哪些操作?
读取磁盘中的fsimage和edit_log到内存
等待datanode的注册信号和块状态信息报告

36.哪些场景才能使用Combiner呢?
不影响最终结果,比如 sum max min 。像avg就不能使用combiner

37.hadoop的TextInputFormat作用是什么,如何自定义实现?
InputFormat会在map操作之前对数据进行两方面的预处理
1是getSplits,返回的是InputSplit数组,对数据进行split分片,每片交给map操作一次
2是getRecordReader,返回的是RecordReader对象,对每个split分片进行转换为
key-value键值对格式传递给map
常用的InputFormat是TextInputFormat,使用的是LineRecordReader对每个分片进行键值对的转换,以行偏移量作为键,行内容作为值

CombineTextInputFormat的切片逻辑跟TextFileInputFormat 不同:它可以将 多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 maptask

38.map-reduce程序运行的时候会有什么比较常见的问题?
map阶段输入的小文件过多
map数量过少导致速度慢
reduce阶段数据倾斜
reduce数量过少

39.mapjoin和reducejoin实现原理


40.Hive中存放是什么?
存的是和hdfs的映射关系
hive的元数据存放在mysql,hive的表数据存放在hdfs

41.分析函数?

42.namenode的safemode是怎么回事?如何才能退出safemode?
namenode在刚启动的时候元数据只有文件块信息,没有文件所在datanode的信息,需要datanode自己向namenode汇报。如果namenode发现datanode汇报的文件块信息没有达到namenode内存中所有文件块的总阈值的一个百分比,namenode就会处于safemode。
只有达到这个阈值,namenode才会推出safemode。也可手动强制退出。

43.一个datanode 宕机,怎么一个流程恢复?
如果是短暂的宕机,可以实现写好脚本监控,将它启动起来。
如果是长时间宕机了,那么datanode上的数据应该已经被备份到其他机器了,
那这台datanode就是一台新的datanode了,删除他的所有数据文件和状态文件,重新启动

44.hadoop 的 namenode 宕机,怎么解决?
先分析宕机后的损失,宕机后直接导致client无法访问,内存中的元数据丢失,但是硬盘中的元数据应该还存在,如果只是节点挂了,
重启即可,如果是机器挂了,重启机器后看节点是否能重启,不能重启就要找到原因修复了。
但是最终的解决方案应该是在设计集群的初期就考虑到这个问题,做namenode的HA。

45.Hive 的join 有几种方式,怎么实现join 的?

3 种join 方式:

1)在reduce 端进行join,最常用的join 方式。
Map 端的主要工作:为来自不同表(文件)的key/value 对打标签以区别不同来源的记录。然后
用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
reduce 端的主要工作:在reduce 端以连接字段作为key 的分组已经完成,我们只需要在每一
个分组当中将那些来源于不同文件的记录(在map 阶段已经打标志)分开,最后进行笛卡尔。

2)在map 端进行join,使用场景:一张表十分小、一张表很大:
在提交作业的时候先将小表文件放到该作业的DistributedCache 中,然后从DistributeCache 中
取出该小表进行join key / value 解释分割放到内存中(可以放大Hash Map 等等容器中)。然后扫描大
表,看大表中的每条记录的join key /value 值是否能够在内存中找到相同join key 的记录,如果有则
直接输出结果

3)SemiJoin,semijoin 就是左边连接是reducejoin 的一种变种,在map 端过滤掉一些数
据,在网络传输过程中,只传输参与连接的数据,减少了shuffle的网络传输量,其他和reduce
的思想是一样的。
实现:将小表中参与join 的key 单独抽取出来通过DistributeCache 分发到相关节点,
在map 阶段扫描连接表,将join key 不在内存hashset 的纪录过滤掉,让参与join 的纪录
通过shuffle 传输到reduce 端进行join,其他和reduce join 一样

46.hadoop的combinet与partition的区别
combine和partition都是函数,中间的步骤应该只有shuffle! combine分为map端和reduce端,作用是把同一个key的键值对合并在一起,可以自定义的,partition是分割map每个节点的结果,按照key分别映射给不同的reduce,也是可以自定义的。这里其实可以理解归类。

47.hadoop的mapreduce的排序发生在几个阶段?

48.Hadoop中InputSplit是什么?
答:InputSplit是指分片,在MapReduce作业中,作为map task最小输入单位。分片是基于文件基础上出来的概念,通俗的理解一个文件可 以切分为多少个片段,每个片段包括了等信息。在 MapTask 拿到这些分片后,会知道从哪开 始读取数据。

49.Hadoop框架中文件拆分是如何被触发的?
答:通过运行输入格式类中的getInputSplit()方法。

50.MapReduce的缺点:
1.一个task任务失败就需要重头再来   没有好的容错机制
2.mapreduce过程频繁的操作磁盘的读写,占用大量资源


3、已知hive中有表A(如下所示),输出对应逻辑的一条hql语句(要求使用两种方法并对比两种方法的执行效率)

表结构:
table A
date string  日期
value int     数值

表数据:
2018-01-01               432
2018-01-02    531
2018-01-03    231
...
2018-01-31    334
2018-02-01    346
...
2018-02-28    387
2018-03-01    537
...
2018-03-31    642
...
2018-06-01    456
...


(当月累计到当日的总和)
输出数据:
2018-01-01    432
2018-01-02    432+531
2018-01-03    432+531+231
...
2018-01-31    432+531+231+...+334
2018-02-01    346
...
2018-02-28    346+...+387
2018-03-01    537
...
2018-03-31    537+...+642
...
2018-06-01    456
...

select date,sum(value) over (distribute by substr(date,1,7) sort by date ) as values
from identify.tmp_0303_1


2、将附件中的数据里面的custid和ord_id提取出来,保存为以tab分割的文本文件,写出脚本,请分别使用java、shell两种语言实现

740574,201702090010754
21955106,201702090010913

2017-02-09 15:55:08    monitor.act_task_10098.flow    
{"userip":"10.4.41.78","request_uri":"/act/index","custid":"17450697",
"request":{"cmd":"40020280","act_id":"GhEtIhs/IXE=","userid":"17450697","data":{"ord_id":"201702090011523"}},
"response":{"code":"0","msg":null},"exe_time":0.041136980056763,"evttime":"2017-02-09 23:55:08","log_level":"3","flowid":"148665570889.424"
}

JSONObject jsonObject = JSONObject.fromObject(obj1);

string custid=jsonObject.get(custid).toString();

JSONObject jsonObjectRequest = jsonObject.getJSONObject("request");

JSONObject jsonObjectDate = jsonObjectRequest.getJSONObject("data");

String ord_id = jsonObjectDate.get(ord_id).toString();;

 

echo '{
 "userip":"10.4.41.78",
 "request_uri":"/act/index",
 "custid":"17450697",
 "request":{
              "cmd":"40020280","act_id":"GhEtIhs/IXE=","userid":"17450697",
              "data":{"ord_id":"201702090011523"}
           },
 "response":{"code":"0","msg":null},
 "exe_time":0.041136980056763,"evttime":"2017-02-09 23:55:08","log_level":"3",
 "flowid":"148665570889.424"
}' | jq '.request|.data|.ord_id' 
| jq '.custid'
| jq '.request|.data|.ord_id' 

 

不用开窗实现开窗效果

 

数仓中那层做维度建模  那层做维度退化

DWD层和DWS层,分别是明细数据层和汇总数据层,采用维度模型方法作为理论基础,更多地采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联,提高明细数据表的易用性:同时在汇总数据层,加强指标的维度退化,采取更多的宽表化手段构建公共指标数据层,提升公共指标的复用性,减少重复加工。
 

不可累加指标(pv,uv ) 怎么从dws到dm层

java中的排序

快排和归并的实现和时间复杂度

left semi join 原理

当A表left semi join关联B表时,结果表只能有A表的列,且B表只能在on中设置过滤条件,并且当B表有重复数据时,A表只会关联B对应值一次

在left semi join中,关联右侧的表只能在on中设置过滤条件,在where, select或其他地方均不可出现。这主要是因为left semi join只会传递关联条件中key给每一个map,这导致了查询结果中只会出现左侧表中的相关内容

因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。这就导致右表有重复值得情况下 left semi join 只产生一条,join 会产生多条,也会导致 left semi join 的性能更高

数据库和数据仓库

数据库(OLTP):传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。

数据仓库(OLTP):数据仓库系统的主要应用主要是OLAP(On-Line Analytical Processing),支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。

hive实现行转列 列转行

行转列

select max(sno), name
   , concat_ws(',', collect_set(DEPART)) as DEPART 
from students_info
group by name

列转行

select SNO, name, add_DEPART
from students_info si 
lateral  view explode(split(si.DEPART,','))  b AS add_DEPART

 

sqoop 的null处理

sqoop import  \
    --connect "jdbc:mysql://${hostname}:3306/${db_name}?useUnicode=true&characterEncoding=UTF-8" \
    --username ${user_name} \
    --password ${pwd} \
    --table ${table_name} \
    --null-string '\\N'  \
    --null-non-string '\\N' \
    --fields-terminated-by '\t' \
    --lines-terminated-by '\n' \
    --hive-import  \
    --hive-overwrite \
    -z \
    --compression-codec lzo \
    -m 1 \
    --hive-table ${table_name}

alter table ${table_name} SET SERDEPROPERTIES('serialization.null.format' = '\\N'); 

上面的导入命令要去掉–direct选项

MR实现全局排序

实现MapReduce全局排序有三种方法:

  1. 使用一个reduce实现全局排序
  2. 自定义分区函数实现全局排序
  3. 使用TotalOrderPartitoner进行全局排序

https://www.iteblog.com/archives/2146.html

public class TotalSortV2 extends Configured implements Tool {
    static class SimpleMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> {
        @Override
        protected void map(LongWritable key, Text value,
                           Context context) throws IOException, InterruptedException {
            IntWritable intWritable = new IntWritable(Integer.parseInt(value.toString()));
            context.write(intWritable, intWritable);
        }
    }
 
    static class SimpleReducer extends Reducer<IntWritable, IntWritable, IntWritable, NullWritable> {
        @Override
        protected void reduce(IntWritable key, Iterable<IntWritable> values,
                              Context context) throws IOException, InterruptedException {
            for (IntWritable value : values)
                context.write(value, NullWritable.get());
        }
    }
 
    public static class IteblogPartitioner extends Partitioner<IntWritable, IntWritable> {
        @Override
        public int getPartition(IntWritable key, IntWritable value, int numPartitions) {
            int keyInt = Integer.parseInt(key.toString());
            if (keyInt < 10000) {
                return 0;  //写死分区编号
            } else if (keyInt < 20000) {
                return 1;
            } else {
                return 2;
            }
        }
    }

连续活跃天数

使用lag(向后)或者lead(向前)
select 
user_id,t1.dt,
lead(t1.dt) over(partition by user_id order by t1.dt) as last_date_id
from 
(
select DISTINCT dt,user_id from test5active
)t1;

连续活跃两天以上的用户
select
distinct t2.user_id
from 
(
select 
user_id,t1.dt,
lead(t1.dt) over(partition by user_id order by t1.dt) as last_date_id
from 
(
select DISTINCT dt,user_id from test5active
)t1
)t2 where datediff(last_date_id,t2.dt)=1;
连续三天登录用户,当天的前一条和后一条都相差一天
select user_id
from
(
	select user_id
	from
	(select user_id,
			lag(login_date,1) over(partition by user_id order by login_date) as lag_login_date,
			login_date,
			lead(login_date,1) over(partition by user_id order by login_date) as lead_login_date
			from dwd.login_log
	)t1
	where datediff(login_date,lag_login_date)=1 and datediff(lead_login_date,login_date)=1
)t2
group by user_id;

 

 

 

 

 

 

 

 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值