17、Hive面试总结
1、Hive导出数据有几种方式?如何导出数据
(1)insert
导出本地:
insert overwrite local directory '本地路径' select * from 表名;
导出到HDFS:
insert overwrite directory 'hdfs路径' select * from 表名;
(2)hadoop命令
hdfs dfs -get /user/hive/warehouse/student/student/txt /opt/bigdata/data
(3)Bash shell
$bin/hive -e "select * from b"
(4)export导出hdfs
export table default.student to 'hdfs路径'
2、将一个表的数据按照指定的分隔符(@)导出一各文件
insert overwrite local directory '本地路径' rom format delimited fields terminated by '@' select * from 表名;
3、分区和分桶的区别
分区:
是指按照数据表的某列或这某些列分为多个区,区从形式来讲可以理解为文件夹,比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天回生成大量的数据,导数数据表的内容过于巨大,在查询的时候权标扫描耗费的资源非常多。可以按照日期对数据进行分区,不同日期的数据存放在不同的分区在,查询时只要指定分区字段的值就可以直接从该分区进行查找。
分桶:
分桶是相对于分区进行更细粒度的划分,分桶将整个数据内容按照某列属性hash值进行划分,如果按照name属性分为3个桶,就是对name属性值进行hash值对3取模,按照取模结果对数据进行分桶。取模结果为0的数据记录存放在到一个文件.....取模为2的数据存放在一个文件。
总结:
分区就是在HDFS上进行分目录,分桶就是分文件。
4、将数据直接上传到分区目录(hdfs)上,让分区表和数据产生骨关联有些方式
方案一:上传数据后修复
dfs -mkdir -p 分区目录
dfs -put 分区目录
msck repair table 表名
方案二:上传数据后添加分区
dfs -mkdir -p 分区目录
dfs -put 分区目录
alter table 表名 add partition();
提示:
这里我们如果将分新的分区上传到hdfs上,因为hive没有对应的元数据所示是无法查询的,所以我们要进行表的修复或者新添加分区。
5、桶表是否可以通过直接load将数据导入
不可以,因为load数据的话hdfs只会有一个文件无法完成分桶的小效果,分桶和mapreduce分区是一样的道理,所以我们要借助中间表进行导入数据。
6、Hive分区是否越多越好
(1)如果有过多的分区,由于底层是存储在hdfs上,HDFS只用于存储大文件,而非小文件,疑问过多的分区会增加namenode的负担
(2)hive会转化为mapreduce,mapreduce会转化为多个task,过多的小文件的话,每个文件一个task,每个task一个JVM实例,JVM的开启会降低系统的效率
7、什么情况下Hive可以避免进行MapReduce
hive为了执行效率,简单的查询,就是知识select,不带count,sum,group by,都不走map/reduce直接读取hdfs目录中的文件进行过滤,也就是本地模式。
(1)直接查询数据不会进行MapReduce
select * from employee;
(2)查询语句中的过滤条件只是区分字段的情况下不会进行MapReduce
select * from order_partition where month = '2019-03'
(3)设置属性set.hive.exec.model.local.auto = true;hive还是会尝试使用本地模式
8、order by,sort by,distribute by ,cluster by区别
(1)order by会对给定的数据进行全局排序不管来多少数据,都启动一个reducer来处理
(2)sort by是局部排序,sort by 会根据数据量的大小启动一个到多个reducer工作,会在进行reduce之前为每个reducer都产生一个排序文件
(3)distribute by控制map结果的分发,将具有相同字段的map输出分发到reduce节点上去。
9、聚合函数是否可以写在order by 后面?
不可以
原因是执行顺序,order by的执行顺序在select之后,所一需要使用重新定义的列名进行排序。
提示:理解sql的执行顺序更加有利于写sql
(1)from
(2)join (3)on (4)where (5)select (6)group by (7)having (8)order by (9)limit
10、级联求和
1、需求
| 访客 | 月份 | 访问次数 | | ---- | ------- | -------- | | A | 2015-01 | 5 | | A | 2015-01 | 15 | | B | 2015-01 | 5 | | A | 2015-01 | 8 | | B | 2015-01 | 12 | | A | 2015-01 | 2 | | A | 2015-01 | 12 | | A | 2015-02 | 13 | | B | 2015-02 | 6 | | B | 2015-02 | 5 | | B | 2015-02 | 7 |
2、需要输出报表
| 访客 | 月份 | 月访问统计 | 累计访问统计 | | ---- | ------- | ---------- | ------------ | | A | 2015-01 | 33 | 33 | | A | 2015-02 | 10 | 43 | | B | 2015-01 | 15 | 15 | | B | 2015-02 | 20 | 35 |
3、实现步骤
(1)创建一个表
create table t_access_time(
username string,
month string,
salary int
)
row format delimited fields by ','
(2)准备数据
A,2015-01,5 A,2015-01,15 B,2015-01,5 B,2015-01,25 A,2015-01,5 A,2015-02,12 A,2015-02,5 B,2015-02,5 B,2015-02,5 B,2015-02,5
(3)导入数据
load data local inpath '/opt/bigdata2.7/access.log' into table t_access_time
(4)步,先求个用户月总金额
select username,sum(salary) as salary from t_access_time group by username,month;
(5)第二步,将月总金额表 自己和自己join(自join)
select A.,B. from (select username,month,sum(salary) as salary from t_access_time group by username,month) A iner join (select username,month,sum(salary) as salary from t_access_time group by username,month) B on A.username=B.username where B.month<=A.month;
(6)第三步,从上一步的结果尽心分组查询,分组的字段是a.username,a.month,求月累计值,将b.month<=b.month的所有b.salary求和既可。
select A.username,A.month,max(A.salary) as salary,sum(B.salary) as accumulate from (select username,month,sum(salary) as salary from t_access_time group by username,month) A iner join (select username,month,sum(salary) as salary from t_access_time group by username,month) B on A.username=B.username where B.month<=A.month group by A.username,A.month order by A.username,A.month;
相关文章