Hive函数函数及性能优化
Hive函数分类
- 从输入输出角度分类
- 标准函数:一行数据中的一列或多列为输入,结果为单一值
- 聚合函数:多行的零列到多列为输入,结果为单一值
- 表生成函数:零个或多个输入,结果为多列或多行
- 从实现方式分类
- 内置函数
- 自定义函数
2.1 UDF:自定义标准函数
2.2 UDAF:自定义聚合函数
2.3 UDTF:自定义表生成函数
内置函数
- Hive提供大量内置函数供开发者使用
- 标准函数
字符函数
类型转换函数
数学函数
日期函数
集合函数
条件函数 - 聚合函数
- 表生成函数
字符函数
- locate
- split and str_to_map
类型转换函数和数学函数
- binary
- cast
日期函数
集合函数
条件函数
对比:
聚合函数和表生成函数
- 聚合函数
- count、sum、max、min、avg、var_samp等
- 表生成函数:输出可以作为表使用
- expload
- stack
Hive UDF开发流程
- 继承UDF类或GenericUDF类
- 重写evaluate()方法并实现函数逻辑
- 编译打包为jar文件
- 复制到正确的HDFS路径
- 使用jar创建临时/永久函数
- 调用函数
Hive UDF实现
- Java IDE, JDK, Maven
- 继承UDF并重写evaluate()方法
- 编译、测试和打包jar文件,上传jar并调用函数
- 临时udf函数
在hive命令行中使用add jar jar包路径即可加载到临时系统中
create temporary function 函数名 as ‘方法的全类名’;
案例:.在一个时间基础上,进行小时的加减,得到新的时间
add jar /root/teststudf.jar;
create temporary function add_hour as 'cn.kgc.testUdf.AddHour';
运用函数select add_hour(参数1,参数2);
- 永久udf函数
在linux命名行使用hdfs命令把jar上传到hdfs的路径
create function 函数名 as ‘方法的全类名’ using jar ‘jar包的hdfs路径’
案例:计算两个时间的时间差
yum install -y zip
zip -d teststudf.jar 'META-INF/.SF' 'META-INF/.RSA' 'META-INF/*SF'
hdfs dfs -put teststudf.jar /apps/hive/functions/
create function hour_diff as 'cn.kgc.testUdf.HourDiff' using jar 'hdfs:apps/hive/functions/teststudf.jar';
Hive事务
概述
事务(Transaction )指一组单元化操作,这些操作要么都执行,要么都不执行
特性
ACID特性(同sql)
Atomicity:原子性
Consistency:一致性
Isolation:隔离性
Durability:持久性
特点
- V0.14版本开始支持行级事务
- 支持INSERT、DELETE、UPDATE(v2.2.0开始支持Merge)
- 文件格式只支持ORC
局限
- 表必须是bucketed表
- 需要消耗额外的时间、资源和空间
- 不支持开始、提交、回滚、桶或分区列上的更新
- 锁可以为共享锁或排它锁(串联的而不是并发)
- 不允许从一个非ACID连接读写ACID表
- 使用较少
Hive事务的开启和设置
- 通过Hive命令行方式设置,当前session有效
set hive.support.concurrency = true;
set hive.enforce.bucketing = true;
set hive.exec.dynamic.partition.mode = nonstrict;
set hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
set hive.compactor.initiator.on = true;
set hive.compactor.worker.threads = 1;
- 通过配置文件设置,全局有效
-- 通过配置文件hive-site.xml
<property>
<name>hive.support.concurrency</name>
<value>true</value>
</property>
<property>
<name>hive.txn.manager</name> <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
Hive PLSQL
- Hive PLSQL:Hive存储过程(v2.0之后)
- 支持SparkSQL和Impala
- 兼容Oracle、DB2、MySQL、TSQL标准
- 使将现有的过程迁移到Hive变得简单和高效
- 使编写UDF不需要Java技能
- 它的性能比Java UDF稍微慢一些
- 功能较新
- 在Hive2 bin目录下运行./hplsql
./hplsql -f plsql_demo.pl
returns string
begin return 'Hello, ' || text || '!';
end;
print hello(' word')
create procedure getCount()
begin declare cnt int = 0;
select count(*) into cnt from employee;
print 'Users cnt: ' || cnt;
end;
call getCount();
Hive性能调优工具
EXPLAIN
- explain:显示查询语句的执行计划,但不运行
- 语法
explain [extended|dependency|authorization] hive_query
- extended
提供执行计划关于操作的额外信息,比如文件路径 - dependency
提供JSON格式输出,包括查询所依赖的表和分区列表 - authorization
列出所有需要授权的实体,包括查询的输入输出和授权失败 - 通过工具生成可视化执行计划
ANALYZE
- analyze:分析表数据,用于执行计划选择的参考
- 收集表的统计信息,如行数、最大值等
- 使用时调用该信息加速查询
- 语法
analyze table employee compute statistics; //预先加载
analyze table employee_partitioned
partition(year=2014, month=12) compute statistics;
analyze table employee_id compute statistics
for columns employee_id;
Hive优化设计
- Hive支持将作业自动转换为本地模式运行
- 当要处理的数据很小时,完全分布式模式的启动时间比作业处理时间要长
-- 通过以下设置开启本地模式
SET hive.exec.mode.local.auto=true; --default false
SET hive.exec.mode.local.auto.inputbytes.max=50000000;
SET hive.exec.mode.local.auto.input.files.max=5; --default 4
- Job必须满足以下条件才能在本地模式下运行
- Job总输入大小小于 hive.exec.mode.local.auto. inputbytes.max
- map任务总数小于 hive.exec.mode.local.auto. input.files.max
- 所需的Reduce任务总数为1或0
Job优化 - JVM重用(JVM Reuse)
- 通过JVM重用减少JVM启动的消耗
- 默认每个Map或Reduce启动一个新的JVM
- Map或Reduce运行时间很短时,JVM启动过程占很大开销
- 通过共享JVM来重用JVM,以串行方式运行MapReduce Job
- 适用于同一个Job中的Map或Reduce任务
- 对于不同Job的任务,总是在独立的JVM中运行
-- 通过以下设置开启JVM重用
set mapred.job.reuse.jvm.num.tasks = 5; -- 默认值为1
查询优化
- 自动启动Map端Join,适合一个大表一个小表
- 防止数据倾斜
set hive.optimize.skewjoin=true;
- 启用CBO(Cost based Optimizer)
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true; //计算每个列的使用情况 一般针对大表
set hive.stats.fetch.partition.stats=true;//分区的负载均衡
- 启动Vectorization(矢量化也叫有序化)
set hive.vectorized.execution.enabled = true;
set hive.vectorized.execution.reduce.enabled = true;
- 使用CTE、临时表、窗口函数等正确的编码约定
压缩算法
- 减少传输数据量,会极大提升MapReduce性能
采用数据压缩是减少数据量的很好的方式 - 常用压缩方法对比
一般常用gzip和snappy类型进行压缩,不可分割,速度快
超大型文件一般用bzip2类型进行压缩,但是时间很长