hive学习

Hive

概述

什么是Hive

hive是基于Hadoop的数据仓库建模工具之一,使用类sql语言,对存储在hdfs上的数据进行分析和管理。传入一条交互式sql在海量数据中查询分析结果的工具。

hive的优缺点

优点

1、操作接口采用类sql语法,提供快速开发的能力(简单、容易上手)

2、避免了去写MapReduce,减少开发人员的学习成本

3、Hive的延迟性比较高,因此Hive常用于数据分析,适用于对实时性要求不高的场合

4、Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高。(不断地开关JVM虚拟机)

5、Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。

6、集群可自由扩展并且具有良好的容错性,节点出现问题SQL仍可以完成执行

缺点

1、Hive的HQL表达能力有限

(1)迭代式算法无法表达 (反复调用,mr之间独立,只有一个map一个reduce,反复开关)

(2)数据挖掘方面不擅长

2、Hive 的效率比较低

(1)Hive 自动生成的 MapReduce 作业,通常情况下不够智能化

(2)Hive 调优比较困难,粒度较粗 (hql根据模板转成mapreduce,不能像自己编写mapreduce一样精细,无法控制在map处理数据还是在reduce处理数据)

特点

1、可扩展性

Hive可以自由的扩展集群的规模,一般情况下不需要重启服务

2、延申性

Hive支持自定义函数,用户可以根据自己的需求来实现自己的函数

3、容错

即使节点出现错误,SQL仍然可以完成执行

hive的交互方式

1)第一种交互方式

shell交互Hive,用命令hive启动一个hive的shell命令行,在命令行中输入sql或者命令来和Hive交互。

服务端启动metastore服务(后台启动):nohup hive --service metastore > /usr/local/soft/mylogs 2>&1 &
进入命令:hive
退出命令行:quit;

2)第二种交互方式

Hive启动为一个服务器,对外提供服务,其他机器可以通过客户端通过协议连接到服务器,来完成访问操作,这是生产环境用法最多的

服务端启动hiveserver2服务:
nohup hive --service metastore >/dev/null &
nohup hiveserver2 >/dev/null &

需要稍等一下,启动服务需要时间:
进入命令:1)先执行: beeline ,再执行: !connect jdbc:hive2://master:10000
       2)或者直接执行: beeline -u jdbc:hive2://master:10000 -n root
退出命令行:!exit

3)第三种交互方式

使用 –e 参数来直接执行hql的语句

bin/hive -e "show databases;"

使用 –f 参数通过指定文本文件来执行hql的语句

特点:执行完sql后,回到linux命令行。

vim hive.sql

use myhive;
select * from test;
hive -f hive.sql

hive的数据类型

类型Java数据类型描述
TINYINT byte 8位有符号整型。取值范围:-128~127。
SMALLINT short 16位有符号整型。取值范围:-32768~32767。
INT int 32位有符号整型。取值范围:-2 31 ~2 31 -1。
BIGINT long 64位有符号整型。取值范围:-2 63 +1~2 63 -1。
BINARY   二进制数据类型,目前长度限制为8MB。
FLOAT float 32位二进制浮点型。
DOUBLE double 64位二进制浮点型。
DECIMAL(precision,scale)   10进制精确数字类型。precision:表示最多可以表示多少位的数字。取值范围:1 <= precision <= 38。scale:表示小数部分的位数。取值范围: 0 <= scale <= 38。如果不指定以上两个参数,则默认为decimal(10,0)。
VARCHAR(n)   变长字符类型,n为长度。取值范围:1~65535。
CHAR(n)   固定长度字符类型,n为长度。最大取值255。长度不足则会填充空格,但空格不参与比较。
STRING string 字符串类型,目前长度限制为8MB。
DATE   日期类型,格式为yyyy-mm-dd。取值范围:0000-01-01~9999-12-31。
DATETIME   日期时间类型。取值范围:0000-01-01 00:00:00.000~9999-12-31 23.59:59.999,精确到毫秒。
TIMESTAMP   与时区无关的时间戳类型。取值范围:0000-01-01 00:00:00.000000000~9999-12-31 23.59:59.999999999,精确到纳秒。说明 对于部分时区相关的函数,例如cast(<a timestamp> as string),要求TIMESTAMP按照与当前时区相符的方式来展现。
BOOLEAN boolean BOOLEAN类型。取值:True、False。

hive分区

在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天或者每小时切分成一个个小的文件,这样去操作小的文件就会容易很多了。

静态分区(sp)

借助于物理的文件夹分区,实现快速检索的目的。

一般对于查询比较频繁的列设置为分区列。

分区查询的时候直接把对应分区中所有数据放到对应的文件夹中。

动态分区(dp)

静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。

详细来说,静态分区的列是在编译时期通过用户传递来决定的;动态分区只有在SQL执行时才能决定。

优点:不用手动指定了,自动会对数据进行分区

缺点:可能会出现数据倾斜

hive分桶
为什么需要分桶

分区提供了一个隔离数据和优化查询的便利方式,不过并非所有的数据都可形成合理的分区,尤其是需要确定合适大小的分区划分方式 不合理的数据分区划分方式可能导致有的分区数据过多,而某些分区没有什么数据的尴尬情况 分桶是将数据集分解为更容易管理的若干部分的另一种技术。 分桶就是将数据按照字段进行划分,可以将数据按照字段划分到多个文件当中去。

优势
方便抽样

使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便

提高join查询效率

获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

原理

Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

bucket num = hash_function(bucketing_column) mod num_buckets

列的值做哈希取余 决定数据应该存储到哪个桶

分桶的支持

set hive.enforce.bucketing=true;

hive的四个排序

全局排序order by

order by 会对输入做全局排序,因此只有一个reducer**,会导致当输入规模较大时,需要较长的计算时间

使用 order by子句排序 :ASC(ascend)升序(默认)| DESC(descend)降序

order by放在select语句的结尾

select * from 表名 order by 字段名1[,别名2...];
局部排序sort by

sort by 不是全局排序,其在数据进入reducer前完成排序

如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by 只保证每个reducer的输出有序,不保证全局有序。asc,desc

设置reduce个数

set mapreduce.job.reduce=3;
set mapred.reduce.tasks=3;

查看reduce个数

set mapreduce.job.reduce;

排序

select * from 表名 sort by 字段名[,字段名...];
分区排序distribute by

distribute by(字段)根据指定的字段将数据**分到不同的reducer,且分发算法是hash散列。

类似MR中partition,进行分区,结合sort by使用。**(注意:distribute by 要在sort by之前)

对于distrbute by 进行测试,一定要多分配reduce进行处理,否则无法看到distribute by的效果。设置

reduce个数

set mapreduce.job.reduce=7;

排序

select * from 表名 distribute by 字段名[,字段名...];
分区并排序cluster by

cluster by(字段)除了具有Distribute by的功能外,还会对该字段进行排序

cluster by = distribute by + sort by 只能默认升序,不能使用倒序

select * from 表名 sort cluster by 字段名[,字段名...];
select * from 表名 distribute by 字段名[,字段名...] sort by 字段名[,字段名...];

hive自定义函数

UDF 进一出一
UDAF 进多出一

collect_set()和collect_list()都是对多列转成一行,区别就是list里面可重复而set里面是去重的 concat_ws(':',collect_set(type)) ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据 select 字段名,concat_ws(':',collect_set(列名)) as 别名 from 表名 group by id;

UDTF 进一出多

explode 可以将一组数组的数据变成一列表 select explode(split(列名,"数据的分隔符")) from 表名; lateral view 表生成函数,可以将explode的数据生成一个列表 select id,name,列名 from 表1,lateral view explode(split(表1.列名,"数据的分隔符"))新列名 as 别列名;

hive的排序开窗函数

RANK()、DENSE_RANK() 、ROW_NUMBER() 、PERCENT_RANK()。

1.RANK() 排序相同时会重复,总数不会变

2.DENSE_RANK() 排序相同时会重复,总数会减少

3.ROW_NUMBER() 会根据顺序计算

4.PERCENT_RANK()计算给定行的百分比排名。可以用来计算超过了百分之多少的人(当前行的rank值-1)/(分组内的总行数-1)

hive join数据倾斜

什么是数据倾斜

同一个key进入同一个reduce,如果key对应的数据量很多,那么这个reduce的处理数据压力就会变大,可能会导致任务崩溃。

解决方法

分散key对应的数据 ,减小压力。改变随机前缀。再开启一个reduce和map任务

join时发生数据倾斜

1.小表join小表时不会发生

2.小表join大表时开启map-join

3.大表join大表:map-side、空key过滤、空key转换

join计算的时候,将小表(驱动表)放在join的左边 Map join:在Map端完成join 两种实现方式: 1、sql方式,在sql语句中添加Mapjoin标记(mapjoin hint)

语法:

select /*+MAPJOIN(smallTable)*/ smallTable.key bigTable.value from smallTable join bigTable on smallTable.key=bigTable.key;

2、自动开启mapjoin 通过修改以下配置启用自动的mapjoin: set hive.auto.convert.join=true; (注意:该参数为true的时候,Hive自动对左边的表统计量,如果 是小表,就加入到内存,即对小表使用Mapjoin)

相关配置参数   hive.mapjoin.smalltable.filesize;(默认25M,大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行。)   hive.ignore,mapjoin.hint;(默认值:true;是否忽略mapjoin hint的标记)   hive.auto.convert.join.noconditionaltask;(默认值:true;将普通的join转换为mapjoin时,是否将多个mapjoin转化为一个mapjoin)   hive.auto.convert.join.noconditionaltask.size;(将多个mapjoin转化为一个mapjoin时,这个表的最大值) 3、尽可能使用相同的连接键,如果不同,多一个join就会多开启一个mapreduce,执行速度变得慢。 4、大表join大表(当两个都是大表的时候,只能发生reduce了,但是这里有两个优化策略)(面试的时候说,加分)   a: 空key过滤:     有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的 reducer上,从而导致内存不够。     此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。     但是这个的前提条件是异常数据,但是我们一般拿到的数据都是经过ETL数据清洗过后的,一般影响不大,面试的时候可以说。   b: 空key转换:     有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,     此时我们可以表a中key为空的字段赋随机的值,使得数据随机均匀地分不到不同的 reducer上。     但是我们一般拿到的数据都是经过ETL数据清洗过后的,规则数据,一般影响不大,面试的时候可以说。 5、Map-Side聚合 通过设置以下参数开启在Map端的聚合 set hive.map.aggr=true;(一定要进行开启,虽然进行了两个mapreduce,但是当数据倾斜发生的时候,很多时候会根本跑不出结果,卡死在99%或者100%,慢总比出不来结果要好)!!!!!!! 相关配置参数   hive. groupby mapaggr. checkinterval;   map端 igroup by执行聚合时处理的多少行数据(默认:10000   hive.map.aggr.hash.min.reduction;比例(若聚合之后的数据100大该0.5,map端聚合使用的内存的最大值   hive.mapaggr.hashforce.flush.memory.threshold;map端做聚合操作是has表的最大可用内容,大于该值则会触发fush   hive.groupby.skewindata-是否对 GroupBy产生的数据倾斜做优化,默认为false(十分重要!!!) 6、数据倾斜,尽可能地让我们的数据散列到不同的reduce里面去,负载均衡

posted @   wdnmd、  阅读(101)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示