1、hive的作用:

  hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。 相对于mapreduce 离线计算需要写很多java代码去实现数据提取,hive可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用开发程序,更适合数据仓库的统计分析。

2、hive的分区与分桶的区别

(1)hive分区

  在Hive Select查询中一般会扫描整个表内容,但是有时只需要扫描表中部分数据,因此建表时引入了partition概念。分区表指的是在创建表时指定的partition的分区空间。 Hive可以对数据按照某列或者某些列进行分区管理。

  1)分区原因:Hive中的分区其实就是分目录,根据某些维度(例如时间等)将数据表分成多份,一个分区表对应HDFS文件系统上一个独立的文件夹,该文件夹下是该分区所有的数据文件;查询时,通过where表达式选择查询所指定的分区即可,不用再查询整张表的所有数据,提高海量数据查询的效率。

(2)hive桶

  对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

  1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

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

3、内部表与外部表的关系

(1)未被external修饰的是内部表【managed table】,被external修饰的为外部表【external table】。

(2)内部表数据由Hive自身管理,外部表数据由HDFS管理。

(3)内部表数据存储在hive.metastore.warehouse.dir【默认:/user/hive/warehouse】,外部表数据存储位置由用户自己决定

(4)删除内部表会直接删除元数据【metadata】及存储数据,删除外部表仅仅删除元数据,HDFS上的文件不会被删除。

(5)对内部表的修改会直接同步到元数据,而对外部表的表结构和分区进行修改,则需要修改【MSCK REPAIR TABLE table_name】。

4、hive的架构:

(1)用户接口:CLI,client,wui.

(2)元数据存储:Hive 将元数据存储在数据库中,如 mysql、derby。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等

(3)解释器,编译器,优化器,执行器:生成的查询计划存储在 HDFS 中,并在随后由 MapReduce 调用执行。

5、hive是如何将HQL语句转化为mapreduce

  接收到用户的指令(HQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。

(1)将HQL进行词法,语法解析,将其L转化为抽象语法树AST Tree

(2)遍历AST Tree,抽象出查询的基本组成单元即查询块

(3)遍历QueryBlock,将其翻译为执行操作树OperatorTree

(4)用逻辑层优化器对OperatorTree进行优化,合并不必要的ReduceSinkOperator,减少MapReduce Job,减少shuffle数据量

(5)遍历OperatorTree,翻译为MapReduce任务树

(6)物理层优化器对MapReduce任务树进行优化,生成最终的执行计划。

6、hive的存储格式

(1)建表时默认为这个格式,导入数据时会直接把数据文件拷贝到hdfs上不进行处理。SequenceFile、RCFile、ORC格式的表不能直接从本地文件导入数据,数据要先导入到TextFile格式的表中,然后再从TextFile表中用insert导入到SequenceFile、RCFile表中。

  1)TextFile:文件不支持块压缩,默认格式,数据不做压缩,磁盘开销大,数据解析开销大。这边不做深入介绍。

  2)RCFile:是Hadoop中第一个列文件格式。能够很好的压缩和快速的查询性能,但是不支持模式演进。 RCFile是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。其次,块数据列式存储,有利于数据压缩和快速的列存取。

  3)ORCFile:存储方式:数据按行分块 每块按照列存储 ,压缩快 快速列存取,效率比rcfile高,是rcfile的改良版本,相比RC能够更好的压 缩,能够更快的查询,但还是不支持模式演进

  4) Parquet:能够很好的压缩,有很好的查询性能,支持有限的模式演进。但是写速度通常比较慢。这中文件格式主要是用在Cloudera Impala上面的。

 读操作:ORC<Parquet<RCFile<TextFile

 存储操作:ORC<Parquet<RCFile<TextFile

注意:在hive中使用压缩需要灵活的方式,如果是数据源的话,采用RCFile+bz或RCFile+gz的方式,这样可以很大程度上节省磁盘空间;而在计算的过程中,为了不影响执行的速度,可以浪费一点磁盘空间,建议采用RCFile+snappy的方式,这样可以整体提升hive的执行速度。

7、udf(用户自定义函数)

(1)介绍:Hive自定义函数包括三种UDF、UDAF、UDTF

  1、UDF(用户自定义函数):一进一出(输入一行,输出一行),例如:upper(),lowser()

  2、UDAF(用户自定义聚合函数):多进一出(输入多行,输出一行),例如:avg(),sum()

  3、UDTF(用户自定义生成函数):一进多出(输入一行,输出多行),例如:lateral view explode

(2)使用方式:针对所操作的数据类型选择不同API;若是基本数据类型则继承UDF,若是Map,Set,List数据类型则继承GenericUDF

  1)创建自定义函数类继承UDF类,实现evaluate方法。

2.3.3/lib库中,同时在hive端利用add命令添加jar包

  3)创建临时函数ccreate temporary function sayhello as 'com.ruozedata.bigdata.HelloUDF';

8、hive的数据倾斜

(1)原因:key分布不均匀,业务数据本身的特性,建表时考虑不周,某些SQL语句本身就有数据倾斜.

(2)解决方法:

  1)参数调节:

   a、hive.map.aggr = true,Map 端部分聚合,相当于Combiner

   b、hive.groupby.skewindata=true

    数据倾斜的时候进行负载均衡,当项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,这样会使相同的Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的。

    第二个MR Job根据预处理的数据将相同的Key分配到同一个Reduce 中最后完成最终的聚合操作。

  2)HQL语句调节:使用map join让小的维度表(1000条以下的记录条数) 先进内存。在map端完成reduce.

  3)空值产生的数据倾斜:赋与空值分新的key值.

9、hive的性能优化

(1)hive的严格模式:某些查询在严格 模式下无法执行。

  1)尽量避免使用order by子句,必须使用limit语句,因为order by子句只会产生一个reducer任务

  2)当表为分区表时,where子句后无分区字段和限制字段禁止执行。

  3)限制笛卡尔乘积的查询。

(2)优化HiveQL语句,join前先过滤等。

  1)尽量避免在 where 子句中使用!=或<>操作符,因为容易全表扫描

  2)in 和 not in 也要慎用,否则会导致全表扫描

(3)设计好分区表和外部表,创建外部表尽量指定数据所在的文件夹,而不用load去加载。

(5)在mapreduce过程中尽量使用压缩,即在map,shuffle,reducer使用snappy压缩。

(5)JVM重用:一个job可能有多个map和reducer任务,每个任务会开启一个jvm虚拟机,默认情况下一个task对应一个jvm,任务完成就销毁jvm,我们可以设置jvm重用参数,这样一个jvm可以连续运行对个任务。   

  缺点:开启JVM重用将会一直占用使用到的task插槽,以便进行重用,若某个job中的reduce task执行时间要比其他reduce task消耗时间多的话,那么保留的插槽却空闲,无法被其他的job使用,直到所有task都结束才会释放.

(6)使用group by代替distinct进行去重:distinct会被hive翻译成一个全局唯一reduce任务来做去重操作,而group by则会被hive翻译成分组聚合运算,会有多个reduce任务并行处理,每个reduce对收到的一部分数据组,进行每组聚合(去重)。

(7)对表进行join时要将大表放在后面,小表放在前面。或者使用streamtable标记小表

(8)在map端完成join

  1)使用MapJoin(smallTable)标记小标。会优先将一张小表(默认小于25M,可以需要适当调节)的数据加载进内存中,然后大表的数据通过map端进行读取,然后和内存进行匹配,内存的计算速度很高,这样就在内存端进行了操作,不需要shuffle,不需要reduce。

  2)自动的mapjoin:set hive.auto.convert.join = true,该参数为true时,Hive自动对左边的表统计量,如果是小表就加入内存,即对小表使用Map join),其中hive.mapjoin.smalltable.filesize是大小表判断的阈值。