Apache Hive高阶实战

Hive的事务(了解):

一组单元化操作,这些操作要么都执行,要么都不执行,是一个不可分割的工作单位。

Atomicity(原子性):

不可再分割的工作单位,事务中的所有操作要么都发生,要么都不发生。

Consistency(一致性):

事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。

Isolation(独立性):

多个事务并发访问,事务之间是隔离的,

Durability(持久性):

意味着在事务完成以后,该事务锁对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

Hive事务的特点和局限:

从v0.14开始支持行级事务

支持INSERT,DELETE,UPDATE(从v2.2.0开始支持MERGE)

不支持BEGIN,COMMIT和ROLLBACK

不支持桶列或分区列的更新

文件格式只支持ORC

表必须是嵌套的群集表

需要压缩工作,这需要时间、资源和空间

锁可以是S(共享锁)或者X locks(排它锁)

X locks(排它锁)是串行的,而不是并发的

不允许从一个非ACID连接写入/读取ACID表

未完全准备好生产

示例:

CREATE TABLE IF NOT EXISTS employee(

emp_id int,

emp_name string,

dept_name string,

work_loc string

)

PARTITIONED BY (start_date string)

CLUSTERED BY (emp_id) INTO 5 BUCKETS STORED AS ORC TBLPROPERTIES('transactional'='true');

INSERT INTO table employee PARTITION (start_date) VALUES

(1,'Will','IT','Toronto','20100701'),

(2,'Wyne','IT','Toronto','20100701'),

(3,'Judy','HR','Beijing','20100701'),

(4,'Lili','HR','Beijing','20101201'),

(5,'Mike','Sales','Beijing','20101201'),

(6,'Bang','Sales','Toronto','20101201'),

(7,'Wendy','Finance','Beijing','20101201');

 

Update employee set dept_name = ‘HR’ where emp_id = 7;

//正常运行

Update employee set emp_id = 7 where dept_name = ‘HR’;

//报错因为emp_id是分桶列

Update employee set start_date =’ ’ where dept_name = ‘HR’;

//报错因为start_date是分区列

MERGE INTO语句(V2.2之后):

Merge允许基于与源表的连接的结果在目标表上执行操作。

Merge语句是用于数据仓库用例的非常强大的工具。它使SCD类型2的操作在Hive中更容易。

Merge只能在支持ACID的表上执行

标准的语法

MERGE INTO AS T USING AS S ON

WHEN MATCHED [AND ] THEN UPDATE SET

WHEN MATCHED [AND ] THEN DELETE

WHEN NOT MATCHED [AND ] THEN INSERT VALUES

注意:

WHEN不能超过三个;每种类型最多1个:UPDATE/DELETE/INSERT

WHEN NOT MATCHED必须是最后一个WHEN子句。

如果同时存在UPDATE和DELETE子句,则语句中的第一个子句必须包含[AND

expression>]

Hive事务的开启和设置:

在命令行中,为当前会话设置:

    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中设置:

   

        hive.support.concurrency

        true

   

   

        hive.txn.manager

        org.apache.hadoop.hive.ql.lockmgr.DbTxnManager

   

Hive中的UDF(User Defined Function):

Java编写函数;继承UDF类,实现方法evaluate

  1. org.apache.hadoop.hive.ql.exec.UDF
  2. 参数和返回值类型位于org.apache.hadoop.io包

FloatWritable evaluate(final Text a){return t;}

打jar包

    maven依赖

    Hadoop.common,hive-exec

添加jar包到hive

    Add jar …./..jar(路径是Linux本地路径)

创建udf

    Create function

    salary_number as 类名;

用户定义函数(UDF):这提供了一种使用外部函数(在Java中)扩展功能的方法,该外部函数可以在HQL中计算。

UDF:用户定义的函数,按行操作并为一行输出一个结果,例如大多数内置的数学和字符串函数。

UDAF:用户定义的聚合函数,按行或按组操作,结果为每个组输出一行或一行,例如内置的MAX和COUNT函数。

UDTF:用户定义的表生成函数,也可以按行操作,但是它们会生成多个行/表,例如EXPLODE函数。UDTF可以在SELECT之后使用,也可以在LATERAL VIEW语句后使用。

Hive UDF开发步骤:

扩展适当的UDF类或GenericUDF类

重写适当的方法和实现功能逻辑

编译和构建 .jar文件

将jar文件复制到适当的HDFS路径

创建临时或永久性功能jar

检查SHOW/DESC创造的功能

当你不需要的时候删除功能

UDF部署遍历

在shell命令行中,将jar文件上传到HDFS:

hdfs dfs -mkdir -p /apps/hive/functions

hdfs dfs -put -f df-hiveudf-1.0-SNAPSHOT.jar /apps/hive/functions

在beeline中,创建/注册函数:

DROP FUNCTION IF EXISTS str_lower;

DROP FUNCTION IF EXISTS array_contains;

CREATE FUNCTION str_lower AS 'com.datafibers.hiveudf.udf.StringLower'

ADD JAR /apps/hive/functions/df-hiveudf-1.0-SNAPSHOT.jar;

CREATE FUNCTION array_contains AS 'com.datafibers.hiveudf.gudf.ArrayContains'

ADD JAR /apps/hive/functions/df-hiveudf-1.0-SNAPSHOT.jar;

在那之后测试:

select str_lower(name), work_place from employee where array_contains(work_place, 'Toronto');

Hive中PLSQL概述

Hive PLSQL是Hive自v.2以来的一个过程语言接口

它还支持SparkSQL和Impala

兼容Oracle、DB2、MySQL、TSQL标准

它的一个目的是将现有的过程简单有效地迁移到Hadoop Hive

编写UDF不需要Java技能

它的性能比Java UDF稍慢

它仍然是新的

Hive PLSQL环境:

hplsql命令不在$PATH中,因此我们需要直接在它的位置运行它

cd /opt/modules/hive-2.3.4/bin

Apache Hive高阶实战_第1张图片

Hive中PLSQL代码

CREATE FUNCTION hello(text STRING)

RETURNS STRING

BEGIN

RETURN 'Hello, ' || text || '!';

END;

Print hello(' word')

 

[root@sandbox-hdp bin]./hplsql -f plsql_demo.pl

Hello, word!

Hive性能调节:

性能效用:

EXPLAIN—不运行就可以返回查询执行计划

EXPLAIN [EXTENDED|DEPENDENCY|AUTHORIZATION] hive_query

EXTENDED:这为计划中的操作符提供了额外的信息,比如Map和Reduce端文件路径、统计信息和语法树

DEPENDENCY:这提供了JSON格式的输出,其中包含查询所依赖的表和分区的列表。

AUTHORIZATION:列出所有需要授权的实体,包括运行Hive查询和授权失败所需的输入和输出。

ANALYZE—收集统计信息,例如行数、文件数、最大值、最小值、均值,数据库中的表、分区、列等对象上的原始数据大小。这些统计信息作为基于hive成本优化器的输入,所有现代数据库都使用这种方法,使用ANALYZE之后统计出的数据会存在系统中,如果进行相关查询时系统就会直接调用,不需要使用Map-Reduce了。

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;

DESCRIBE EXTENDED table_name

//检查统计信息

设计优化:

  1. 使用分区表(partition),最好提升性能的途径,加快查询速度,最常用的是使用时间进行partition
  2. 使用桶表(bucket),减轻处理数据的压力,要清楚业务逻辑,熟悉主外键
  3. 使用指数(index),有另外一个表,对应主表的信息,在实际项目中用的不多
  4. 使用适当的文件格式,而不是文本,如orc,avro,parquet;做查询,过滤时使用orc,parquet性能比较高
  5. 使用适当的压缩,如snappy,可以减少空间,增加传输速度,但是压缩和解压缩也需要时间
  6. 考虑数据本地化——增加一些复制因子,数据离我们越近处理速度越快,对经常使用的数据进行拷贝
  7. 避免小文件,小文件有两个来源:1. 元数据就是小文件;2. 开发人员操作不当,使用了错误的动态partition分区;小文件的影响:加大NameNode的运行压力,性能会降低,每一个小文件都会占用128MB,如果小文件太多就会占用很多空间;解决小文件的方法:文件合并,Hive在运算时就有很多自动合并文件的功能,也可以写第三方的程序来合并小文件,数据源尽量使用大数据
  8. 使用Tez引擎代替mapreduce
  9. 使用Hive LLAP(在内存读缓存中),比较像线程的想法,之前的Hive每运行一次就会启动一个新的线程,LLAP就在后台一直启动一个线程,会节省一个线程的启动
  10. 考虑在不需要时关闭并发

作业优化—在本地模式下运行:

当要处理的数据很小时,启动分布式数据处理是一种开销,因为完全分布式模式的启动时间比作业处理时间要长。Hive支持在本地模式下自动转换作业,设置如下:

直接使用set+想要查询的参数就可以查看这个参数现在设置的参数

    SET hive.exec.mode.local.auto=true;

    //默认值是false

    SET hive.exec.mode.local.auto.inputbytes.max=50000000;

    SET hive.exec.mode.local.auto.input.files.max=5;

    //默认值是4

作业必须满足以下条件才能在本地模式下运行:

         作业的总输入大小小于hive.exec.mode.local.auto. inputbytes.max

         映射任务的总数小于hive.exec.mode.local.auto. input.files.max

         reduce所需的任务总数为1或0

作业优化—JVM重用:

默认情况下,Hadoop为每个map或reduce作业启动一个新的JVM,并并行运行map或reduce任务。当map或reduce作业是只运行几秒钟的轻量级作业时,JVM启动过程可能会带来很大的开销。

MapReduce框架(只有版本1,而不是Yarn)有一个重用JVM的选项,即共享JVM来串行而不是并行地运行mapper/reducer。JVM重用适用于映射或减少同一作业中的任务。来自不同作业的任务总是在单独的JVM中运行。

    SET mapred.job.reuse.jvm.num.tasks=5;

    //默认值是1

作业优化—并行执行:

Hive查询通常被转换成许多按默认顺序执行的阶段。这些阶段并不总是相互依赖的。相反,它们可以并行运行,以节省整个作业运行时间。我们可以通过以下设置启用此功能

    SET hive.exec.parallel=true;

    //默认值是false

    SET hive.exec.parallel.thread.number=16;

    //默认值是8,它定义并行运行的最大数量

并行执行将增加集群的利用率。如果集群的利用率已经非常高,那么并行执行对总体性能没有多大帮助。

查询优化:

确保自动启用map端join

确保桶映射侧连接是自动启用的

对于倾斜数据,设置hive.optimize.skewjoin=true

确保CBO是启用的(默认情况下是启用的)

    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;

确保启用了向量化。它改进了扫描、聚合、筛选和连接等操作,一次执行1024行批次,而不是每次执行一行

    set hive.vectorized.execution.enabled = true;

    set hive.vectorized.execution.reduce.enabled = true;

使用CTE、临时表、窗口函数等适当的编码规定

尽可能使用CTE,避免使用嵌套子查询,还可以使用临时表,省去了很多表;尽量使用窗口函数,有优势,把查询写的十分简单,用简单的操作进行复杂的计算,有效的增加性能。

Hive on MapReduce调优,通常需要注意哪些?

合理设置jobreduce的数量和最大数量

set mapred.reduce.tasks

set hive.exec.reducers.max

合理设置job中每个reduce处理文件的大小

set hive.exec.reducers.bytes.per.reducer

合理设置动态分区

set hive.exec.dynamic.partition

合理设置压缩

map/reduce 输出压缩(一般采用序列化文件存储)

set hive.exec.compress.output=true;

set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;

set mapred.output.compression.type=BLOCK;

任务中间压缩

set hive.exec.compress.intermediate=true;

set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;(常用)

set hive.intermediate.compression.type=BLOCK;

合理设置输入分片

set mapreduce.input.fileinputformat.split.minsize //启动map最小的split size大小,默认0

set mapreduce.input.fileinputformat.split.maxsize //启动map最大的split size大小,默认256M

合理设置合并

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

set hive.merge.mapFiles=true;

set hive.merge.mapredFiles=true;

set hive.merge.size.per.task=xxxx

你可能感兴趣的:(大数据,Hive)