17、Hive面试总结

2020-07-01 00:00:00 查询 数据 文件 分区 目录

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;

相关文章