- 一、基础概念
- 二、常用语法
- 三、优化
- 四、实际操作
- 1、UDF、UDTF
- 2、数据倾斜
- 3、计算map数
- 4、实现exist/in子句
- 5、编写Hive SQL
- 6、内部表转外部表
- 7、null设置默认值?
- 8、语句执行顺序
- 9、有没有使用hive做过权限管理
- 10、Hive有自带的解析json函数,为什么还要自定义UDF、UDTF
- 11、hive海量数据(一个分区)怎么导入MySQL
- 12、原始文件在hdfs上,那数据应该清洗格式化之后才能放到hive吧?/HDFS拷贝到Hive 数据做了哪些处理
- 13、Hive里边字段的分隔符用的什么?为什么用\t?有遇到过字段里边有\t的情况吗,怎么处理的?为什么不用Hive默认的分隔符,默认的分隔符是什么?
- 14、Hive都用过哪些引擎?Tez用的时候设置的容量有多大?设置了哪些参数?
- 15、Hive有没有自己写过UDF函数
- 16、HiveSQL 转MapReduce join 实现怎么处理join关系。写程序,怎么实现两个表join
- 17、Hive的HQL是如何转换为Mr的 例如 select count()from a where r》1 group by …分了几个job task。
- 18、Hive中UDF、UDAF、UDTF的区别
- 19、简述你认为什么样的情况下使用HBase?什么样的情况下使用Hive?
- 20、为什么大多公司不用Hive了,用Impala
- 21、Hive中如何调整map和reduce的个数
- 22、hive以日期分区,问count(*)和count(日期)有什么区别;
- 23、请用java写一个hive udf函数
- 24、hive怎么实现多目录
- 25、hive实现topn
- 26、做hive的时候用过动态分区吗?
- 27、HIVE小文件怎么处理?
- 28、hive和zookeeper的关系
- 29、hive的锁都有哪些,有什么不同的使用场景?
- 30、Hive如何实现负载均衡
一、基础概念
1、概念
Hive是一个基于Hadoop的数仓工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。
本质:将HQL转化成MapReduce程序的计算框架,是MapReduce的封装,底层还是MR
其数据存储在HDFS上,程序运行在yarn上
2、架构
(1)三个用户接口:CLI(本地启动server+副本),Client 和 WUI
(2)元数据存储在数据库中,如mysql、derby
(3)解释器、编译器、优化器完成HQL查询过程生成查询计划,将查询计划存储在HDFS中,随后通过MapReduce调用执行
3、和数据库比较
(1)相似
查询语句相似
(2)不相似
存储位置、数据更新(Hive不建议改写)、执行延迟(Hive延迟高)、数据规模(Hive大规模)
4、内/外部表
(1)比较
1)内部表/管理表:删除管理表时,Hive也会删除对应的数据。内部表不适合和其他工具共享数据。
2)外部表:删除该表并不会删除掉原始数据,删除的是表的元数据
(2)使用:生产环境中为什么建议使用外部表
5、分区/桶表
(1)分区
指按照数据表的某列或某些列(伪列)分为多个区,从形式上可以理解为文件夹
查询:dfs ls(cat) /user/hive/warehouse/testtable/name=jack
查看分区信息:show partitions testtable
(2)分桶
将数据按某列属性的hash值进行区分
分为3个桶,就是对name属性值的hash对3取模,按结果对数据分桶
注意1:执行命令hive.enforce.bucketiong=true;
注意2:clustered by 指定分区依据的列名,还要指定分为多少桶
注意3:分桶是依据数据表中真实的列
实质:将表分成三个文件存储
(3)Hive分区和分桶的区别
6、动态/静态分区
a. 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。
b. 详细来说,静态分区的列是在编译时期,通过用户传递来决定的;动态分区只有在 SQL 执行时才能决定。
c. 动态分区是基于查询参数的位置去推断分区的名称,从而建立分区。
7、Hive中的元数据包括哪些内容,元数据存储在什么位置?
NNNNNNN
8、MapReduce怎么去实现Hive中的mapjoin
NNNNNNNNN
9、Hive常用文件格式介绍一下Orc和Parquet/Hive中使用的数据格式
NNNNNNNNNN
10、Join工作原理,以及mapJoin的工作原理?
NNNNNNNNN
11、sql语句执行流程
NNNNNNNNN
二、常用语法
1、数据类型
(1)基本数据类型
TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING、TIMESTAMP(整数、浮点数或字符串,表示java.sql.TimeStamp时间戳格式)
(2)集合数据类型
STRUCT、MAP、ARRAY
(3)分隔符
\n、^A(分隔字段,建表语句可以用八进制\001表示)、^B(分隔集合类型间的多条数据,可以用\002表示)、^C(Map中键和值的分隔,可以用\003表示)
2、Hql4个By
1)Sort By:分区内有序,有多个reducer☆;
2)Order By:全局排序,只有一个Reducer;
3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。
4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
3、窗口函数
RANK() 排序相同时会重复,总数不会变
DENSE_RANK() 排序相同时会重复,总数会减少
ROW_NUMBER() 会根据顺序计算
1) OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化
2)CURRENT ROW:当前行
3)n PRECEDING:往前n行数据
4) n FOLLOWING:往后n行数据
5)UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
6) LAG(col,n):往前第n行数据
7)LEAD(col,n):往后第n行数据
8) NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。
4、字段分隔符
hive 默认的字段分隔符为ascii码的控制符\001(^A),建表的时候用fields terminated by ‘\001’
遇到过字段里边有\t的情况,自定义InputFormat,替换为其他分隔符再做后续处理
5、自带函数查看
(1)查看month 相关的函数
show functions like ‘month‘
(2)查看 addmonths 函数的用法
**_desc function add_months;
(3)查看 add_months 函数的详细说明并举例
desc function extended **add_months;
6、Hive左连接与内连接的区别
NNNNNNNNNNNN
三、优化
1、对Hive优化
1)MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
2)行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT 。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
3)列式存储
4)采用分区技术
5)合理设置Map数
(1)通常情况下,作业会通过input的目录产生一个或者多个map任务。
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
(2)是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
(3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;
6)小文件进行合并
在Map执行前合并小文件,减少Map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
7)合理设置Reduce数
Reduce个数并不是越多越好
(1)过多的启动和初始化Reduce也会消耗时间和资源;
(2)另外,有多少个Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置Reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的Reduce数;使单个Reduce任务处理数据量大小要合适;
8)常用参数
// 输出合并小文件
SET hive.merge.mapfiles = true; — 默认true,在map-only任务结束时合并小文件
SET hive.merge.mapredfiles = true; — 默认false,在map-reduce任务结束时合并小文件
SET hive.merge.size.per.task = 268435456; — 默认256M
SET hive.merge.smallfiles.avgsize = 16777216; — 当输出文件的平均大小小于16m该值时,启动一个独立的map-reduce任务进行文件merge
9)开启map端combiner(不影响最终业务逻辑)
set hive.map.aggr=true;
10)压缩(选择快的)
设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)
*11)开启JVM重用
四、实际操作
1、UDF、UDTF
或:项目中是否自定义过UDF、UDTF函数,以及用他们处理了什么问题,及自定义步骤?
(1)解决问题:
用UDF函数解析公共字段;用UDTF函数解析事件字段。
(2)使用方式
自定义UDF:继承UDF,重写evaluate方法
自定义UDTF:继承自GenericUDTF,重写3个方法:initialize(自定义输出的列名和类型),process(将结果返回forward(result)),close
(3)为什么要自定义UDF/UDTF,因为自定义函数,可以自己埋点Log打印日志,出错或者数据异常,方便调试。
2、数据倾斜
(1)数据倾斜的表现
Task执行不结束
(2)怎么产生的数据倾斜
不同数据类型关联产生数据倾斜
id字段类型不一致进行join时
情形:比如用户表中userid字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时。
后果:处理此特殊值的reduce耗时,只有一个reduce任务。默认的Hash操作会按int型的id来进行分配,这样会导致**所有string类型id的记录_都分配到一个Reducer中。
解决方式:把数字类型转换成字符串类型
select * from users a
left outer join logs b
on a.usr_id = cast(b.user_id as string)
(3)如何解决
方法1:group by
注:group by 优于distinct group
解决方式:采用sum() group by的方式来替换count(distinct)完成计算。
方法2:mapjoin
方法3:开启数据倾斜时负载均衡
set hive.groupby.skewindata=true;
思想:就是先随机分发并处理,再按照key group by来分发处理。
操作:当选项设定为true,生成的查询计划会有两个MRJob。
第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的原始GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
点评:它使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上。
所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次mr中随机分布到各个节点完成。
方法4:控制空值分布
将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少
实践中,可以使用case when对空值赋上随机值**。此方法比直接写is not null更好,因为前者job数为1,后者为2。
3、计算map数
通常情况下,作业会通过input的目录产生一个或者多个map任务。
决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改);
例如:
input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数。
4、实现exist/in子句
Hive 不支持 where 子句中的子查询, SQL 常用的 exist in 子句需要改写。
例如:
SELECT a. FROM a where a.key in(select dstinct key from b where key like ‘filter%’)
可以写成
SELECT a. FROM a
LEFT OUTER JOIN b ON
(a.key = b.key)
WHERE b.key <> NULL
AND
b.key like ‘filter%’;
5、编写Hive SQL
(1)全量用户登员日志表t_login_all,字段信息ftime(登录日期)、openid(登录帐号)新增用户登录日志表t_login_new,字段信息ftime(登录日期)、openid(登录帐号)求每天新增用户次日、7天、30天留存率。
(说明:7天留存是指当天有登录且第7天还登录的用户)
(2)消息流水表t_chat all,字段信息:
Ftime(日期)、send_user id(发消息用户id)、receive.user id(接收消息用户id)、chat id(消息id)、send.time(发消息时间)
用户登录流水日志表t_login_all,字段信息:
Ftime(日期)、user_id(用户id)、login_id(登录id)、login_loc(登录区服)、login_time(登录时间)
求:每天有收发消息用户最近登录时间、登录区服,输出ftime,user_id,login_loc,login_time
(3)把每科最高分前三名统计出来 —成绩表Score(studentname,student no,subject_no,score)
(4)找出单科成绩高于该科平均成绩的同学名单(无论该学生有多少科,只要有一科满足即可) —成绩表Score(student_name,student_no,subject_no,score)
(5)一个表 test(name,price),构建一个新表,将name相同的,price所有价格合并到一个字段里面
(6)将原Oracle数据库中数据迁移至Hive仓库,请写出“图书”在Hive中的建表语句(Hive实现,提示:列分隔符|;数据表数据需要外部导入:分区分别以month_part、day_part 命名)
(7)Hive中有表A,现在需要将表A的月分区 201505 中 user_id为20000的user_dinner字段更新为bonc8920,其他用户user_dinner字段数据不变,请列出更新的方法步骤。(Hive实现,提示:Hlive中无update语法,请通过其他办法进行数据更新)
(8)在Hive中,查看表member详细描述信息:
(9)在Hive中,向表member中插入一条记录,其中id=a,age=24:
(10)检查并列出下所有“hive/warehouse/dt”文件的状态,请写出相关命令
(11)请写一个创表语句和导入语句,讲.txt的数据导入hive库中
(12)Hive中如何创建自增列
(13)字段a分组 字段b排序 取组内top10
6、内部表转外部表
//建分区表
create table tablePartition(s string) partitioned by(pt string);
alter table tablePartition add if not exists partition(pt=’1’);
alter table tablePartition set TBLPROPERTIES (‘EXTERNAL’=’TRUE’); //内部表转外部表
alter table tablePartition set TBLPROPERTIES (‘EXTERNAL’=’FALSE’); //外部表转内部表
7、null设置默认值?
alter table test_null set serdeproperties(‘serialization.null.format’ = ‘’);
8、语句执行顺序
from>where>group by>having>select>order by
9、有没有使用hive做过权限管理
NNNNNNNNNN
10、Hive有自带的解析json函数,为什么还要自定义UDF、UDTF
NNNNNNNNNN
11、hive海量数据(一个分区)怎么导入MySQL
NNNNNNNNNN
12、原始文件在hdfs上,那数据应该清洗格式化之后才能放到hive吧?/HDFS拷贝到Hive 数据做了哪些处理
NNNNNNNNNN
13、Hive里边字段的分隔符用的什么?为什么用\t?有遇到过字段里边有\t的情况吗,怎么处理的?为什么不用Hive默认的分隔符,默认的分隔符是什么?
NNNNNNNNNN
14、Hive都用过哪些引擎?Tez用的时候设置的容量有多大?设置了哪些参数?
NNNNNNNNNN
15、Hive有没有自己写过UDF函数
NNNNNNNNNN
16、HiveSQL 转MapReduce join 实现怎么处理join关系。写程序,怎么实现两个表join
NNNNNNNNNN
17、Hive的HQL是如何转换为Mr的 例如 select count()from a where r》1 group by …分了几个job task。
NNNNNNNNNN
18、Hive中UDF、UDAF、UDTF的区别
NNNNNNNNNN
19、简述你认为什么样的情况下使用HBase?什么样的情况下使用Hive?
NNNNNNNNNN
20、为什么大多公司不用Hive了,用Impala
Impala:新型查询系统,提供SQL语义,能查询存储再HDFS和HBase中的PB级大数据。
最大卖点是相比较于Hive得快速
NNNNNNNNNN
21、Hive中如何调整map和reduce的个数
NNNNNNNNNN
22、hive以日期分区,问count(*)和count(日期)有什么区别;
NNNNNNNNNN
23、请用java写一个hive udf函数
NNNNNNNNNN
24、hive怎么实现多目录
NNNNNNNNNN
25、hive实现topn
NNNNNNNNNN
26、做hive的时候用过动态分区吗?
NNNNNNNNNN
27、HIVE小文件怎么处理?
NNNNNNNNNN
28、hive和zookeeper的关系
NNNNNNNNNN
29、hive的锁都有哪些,有什么不同的使用场景?
NNNNNNNNNN
30、Hive如何实现负载均衡
NNNNNNNNNN