HiveServer2


Hs挺简单的,现在用的感觉也不是很多,借此简单提一下。

HiveServer2是Hive提供的一种jdbc服务,用户可以通过Hive自带的Beeline连接,也可以使用Java、Python或者PHP等通过jdbc的方式连接。原理是在hive的机器上启动一个server,客户端可以通过ip + port的方式对其进行访问之后,就可以有很多客户端连到这个server上面去干活,可以采用jdbc、odbc、beeline的方式进行连接。但是HiveServer2对多线程的支持并不是很好。基本的编程和基础的Java连接Mysql编程一样。

直接说怎么用吧!

bin/hiveserver2

	bin/beeline

	!connect jdbc:hive2://hadoop-senior.ibeifeng.com:10000 beifeng beifeng org.apache.hive.jdbc.HiveDriver
	
	bin/beeline -u jdbc:hive2:/master:10000/default

HiveServer2 JDBC

将分析的结果存储在hive表(result),前段通过DAO代码,进行数据的查询。

package com.beifeng.senior.hive.jdbc;
	import java.sql.SQLException;
	import java.sql.Connection;
	import java.sql.ResultSet;
	import java.sql.Statement;
	import java.sql.DriverManager;
	
	public class HiveJdbcClient {
		private static final String DRIVERNAME = "org.apache.hive.jdbc.HiveDriver";
	
		/**
		 * @param args
		 * @throws SQLException
		 */
		public static void main(String[] args) throws SQLException {
			try {
				Class.forName(DRIVERNAME);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				System.exit(1);
			}
	
			Connection con = DriverManager.getConnection(//
					"jdbc:hive2://hadoop-senior.ibeifeng.com:10000/default",//
					"root",
					"root"//
				);
			Statement stmt = con.createStatement();
			String tableName = "emp";
	
			// select * query
			String sql = "select * from " + tableName;
			System.out.println("Running: " + sql);
			ResultSet res = stmt.executeQuery(sql);
			while (res.next()) {
				System.out.println(String.valueOf(res.getInt(1)) + "\t" + res.getString(2));
			}
	
		}
	}

这代码是不是看上去很眼熟,其实也就是驱动变了一下 “org.apache.hive.jdbc.HiveDriver”。

数据压缩

压缩的好处大家都可以预见到,就如Windows系统下的压缩一样。举个直观的例子就是通常情况下 block -> map 10G ,10 block,压缩后5G , 5 block。从而可以提高MR的速度。

MR压缩的位置

MR存在可以压缩的位置有一下三部分:

  • map输入压缩
  • map输出到磁盘进行压缩
  • reduce输出进行压缩

压缩配置的位置,map的输入,map输出(中间结果),输出的数据。

Hadoop支持的压缩格式

压缩格式: bzip2, gzip, lzo, snappy等
压缩比:bzip2>gzip>lzo bzip2最节省存储空间
解压速度:lzo>gzip>bzip2 lzo解压速度是最快的

hive创建zstd压缩表_hive创建zstd压缩表

用的最多的是snappy压缩。

数据压缩的好处

  • 数据压缩后使数据量变小
  • map存到本地磁盘,减少IO
  • reduce去拷贝减少网络IO

使用Snappy压缩格式

  1. 安装sanppy(谷歌开源)
  2. 编译haodop 2.x源码
    1.mvn package -Pdist,native -DskipTests -Dtar -Drequire.snappy
    2./opt/modules/hadoop-2.5.0-src/target/hadoop-2.5.0/lib/native
  3. 替换hadoop/lib下的native
  4. 检查是否支持了sanppy bin/hadoop checknative
  5. 在需要压缩时进行配置
  • MapReduce中的压缩
* yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar wordcount -Dmapreduce.map.output.compress=true -Dmapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec /user/beifeng/mapreduce/wordcount/input /user/beifeng/mapreduce/wordcount/output22
  • Hive中设置压缩
  1. Hive中间数据压缩
      hive.exec.compress.intermediate:默认该值为false,设置为true为激活中间数据压缩功能。HiveQL语句最终会被编译成Hadoop的Mapreduce job,开启Hive的中间数据压缩功能,就是在MapReduce的shuffle阶段对mapper产生的中间结果数据压缩。在这个阶段,优先选择一个低CPU开销的算法。
      mapred.map.output.compression.codec:该参数是具体的压缩算法的配置参数,SnappyCodec比较适合在这种场景中编解码器,该算法会带来很好的压缩性能和较低的CPU开销。设置如下:
set hive.exec.compress.intermediate=true
    set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec
    set mapred.map.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;
  1. Hive最终数据压缩
      hive.exec.compress.output:用户可以对最终生成的Hive表的数据通常也需要压缩。该参数控制这一功能的激活与禁用,设置为true来声明将结果文件进行压缩。
      mapred.output.compression.codec:将hive.exec.compress.output参数设置成true后,然后选择一个合适的编解码器,如选择SnappyCodec。设置如下:
set hive.exec.compress.output=true 
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec

数据存储


常用存储格式

file_format:
  : 
  | SEQUENCEFILE(行)
  | TEXTFILE (行)   -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE   (列 )  -- (Note: Available in Hive 0.6.0 and later)
  | ORC      (列 常)   -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET   (列 常)  -- (Note: Available in Hive 0.13.0 and later)
  | AVRO       (列 ) -- (Note: Available in Hive 0.14.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
  • 按行存储数据
  • 按列存储数据(更多时候是对列操作的比如对每一列统计数量等,这样可以减少加载到内存中的数据提高运算速度)

行列存储

ORCFile 存储对比

//1.TEXTFILE文件存储格式
		create table page_views(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS TEXTFILE ;
		
		load data local inpath '/opt/datas/page_views.data' into table page_views ;
		dfs -du -h /user/hive/warehouse/page_views/ ;
		18.1 M  /user/hive/warehouse/page_views/page_views.data
		
		//2.ORC 文件存储格式
		
		create table page_views_orc(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS orc ;         //设置存储格式
		
		insert into table page_views_orc select * from page_views ;
		dfs -du -h /user/hive/warehouse/page_views_orc/ ;
		2.6 M  /user/hive/warehouse/page_views_orc/000000_0

		//3.parquet文件存储格式
		create table page_views_parquet(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS PARQUET ;
		
		insert into table page_views_parquet select * from page_views ;
		dfs -du -h /user/hive/warehouse/page_views_parquet/ ;
		13.1 M  /user/hive/warehouse/page_views_parquet/000000_0
		
		//测试
		select session_id,count(*) cnt from page_views group by session_id order by cnt desc limit 30 ;	
		select session_id,count(*) cnt from page_views_orc group by session_id order by cnt desc limit 30 ;	

		select session_id from page_views limit 30 ;
		select session_id from page_views_orc limit 30 ;
		select session_id from page_views_parquet limit 30 ;
		
		==============================================================
		//4.设置存储格式的同时启动压缩
		//ORC文件存储格式 -Snappy
		create table page_views_orc_snappy(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS orc tblproperties ("orc.compress"="SNAPPY");
		
		insert into table page_views_orc_snappy select * from page_views ;
		dfs -du -h /user/hive/warehouse/page_views_orc_snappy/ ;
		
		//5.ORC文件存储格式-NONE
		create table page_views_orc_none(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS orc tblproperties ("orc.compress"="NONE");
		
		insert into table page_views_orc_none select * from page_views ;
		
		dfs -du -h /user/hive/warehouse/page_views_orc_none/ ;
		
		
		//6.parquet文件存储格式
		set parquet.compression=SNAPPY ;
		create table page_views_parquet_snappy(
		track_time string,
		url string,
		session_id string,
		referer string,
		ip string,
		end_user_id string,
		city_id string
		)
		ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
		STORED AS parquet;
		
		insert into table page_views_parquet_snappy select * from page_views ;
		dfs -du -h /user/hive/warehouse/page_views_parquet_snappy/ ;

注意:这里我改了native文件,因为安装snappy的需要。可能会因为版本不匹配出现问题(我用的Hadoop版本的确和教程不一样)而在hive load数据时候报错,最后我改回来了。慌得一批。自己重新编译一个。

除了常的ORC是行式存储外Parquet也是一种行式存储,同时具有很好的压缩性能;同时可以减少大量的表扫描和反序列化的时间。

hive创建zstd压缩表_hive创建zstd压缩表_02

列式存储的块体现在哪呢?从上面的架构图上可以看出。列式存储的结构是把数据分成若干个Stripe,每个Stripe里面有一个索引。当需要读取数据去时候,它先去扫描每个Stripe里面的index如果扫描到才进行读取。而不是像行存储一样把所有行都扫出来。

Hive优化


  • 优化细节一:FetchTask

大家可能会发现在执行Hive语句时有的语句会去走MR而有的并不会。这是因为Hive的默认配置属性(hive.fetch.task.conversi)导致的 。

默认是 minimal-> (* 、查分区数据、Limit都不走MP)。图上解释的比较清楚。

优化细节二:

  • 大表拆分(字表)
  • 设置外部表分区表
  • 数据格式控制数据压缩
  • SQL语句优化
  • MapReduce优化
  • Reduce Number
  • JVM 重用
  • 推测执行
  • 并行执行
    某些任务之间不存在依赖关系时可以并行执行
  • JVM重用
    Map Task/Reduce Task
    JVM 运行
    启动一个容器,运行多个job
  • Reduce数目(最前面的文章说过了MR调优必调这个)
  • 推测执行(默认启用)最好设置成false
  • Map数目
  • 动态分区调整
  • Strict Mode 严格模式

数据倾斜

数据倾斜在MapReduce编程模型中十分常见,用最通俗易懂的话来说,数据倾斜无非就是大量的相同key被partition分配到一个分区里,造成了’一个人累死,其他人闲死’的情况,这种情况是我们不能接受的,这也违背了并行计算的初衷,首先一个节点要承受着巨大的压力,而其他节点计算完毕后要一直等待这个忙碌的节点,也拖累了整体的计算时间,可以说效率是十分低下的。

数据倾斜容易发生的阶段:

Common/Shuffle/Reduce Join
 	连接发生的阶段,发生在 Reduce Task
 	大表对大表
 	每个表的数据都是从文件中读取的

 Map Join
 	连接发生的阶段,发生在 Map Task
 	小表对大表
 	* 大表的数据放从文件中读取 cid
 	* 小表的数据内存中 id
 	DistributedCache
 SMB Join
 	Sort-Merge-BUCKET Join

例子?:

把这些数据装入32个桶, 然后对应的桶排序,将对应位置的数据Join。这样数据分桶Join比一次性Join快很多。

map join

SMB Map join

附录:

Explain Execution Plan

查看执行计划,看有几个mapreduce任务

explain select deptno, avg(sal)avg_sal from emp group by deptno ;

针对Log日志的解析

正则表达式(见官网)

查看hive函数,很有用的!

show functions;

desc function extend substring;

总结

在Hive数据存储格式中:

数据仓库的特点:一次写入、多次读取,因此,整体来看,ORCFile相比其他格式具有较明显的优势。
TextFile 默认格式,加载速度最快,可以采用Gzip、bzip2等进行压缩,压缩后的文件无法split,即并行处理
SequenceFile 压缩率最低,查询速度一般,三种压缩格式NONE,RECORD,BLOCK
RCfile 压缩率最高,查询速度最快,数据加载最慢。

这篇文章内容整理的有点乱,后面会再次整理一下,同时这部分自我感觉理解不深,有时间去看看比较细节的Hive优化的文章。这部分的内容核心有一下几点,学完后再来回忆如果能想起这些就差不多了。

  • HiverServer2 JDBC
  • 数据压缩
  • 常见压缩格式
  • MR和Hive中怎样进行压缩
  • 数据存储
  • 什么是列式存储
  • 列式存储的特点
  • Hive常见的存储格式(ORC,Parquet)
  • Hive如何设置存储格式
  • 设置存储格式+压缩格式
  • Hive优化
  • 什么是数据倾斜
  • 数据倾斜可能发生阶段
  • 分桶Join
  • 查看Hive函数
  • 查看Hive函数描述