Hive

Hive

原文地址:https://www.cnblogs.com/itboys/tag/HIVE/

Hive是基于Hadoop的数据仓库工具,可对存储在HDFS上的文件中的数据集进行数据整理、特殊查询和分析处理,提供了类似于SQL语言的查询语言——HiveQL,可通过HQL语句实现简单的MR统计,Hive将HQL语句转换成MR任务进行执行。

概述

数据仓库概念

数据仓库(Data Warehouse)是一个面向主题的(Subject Oriented)、集成的(Integrated)、相对稳定的(Non-Volatile)、反应历史变化(Time Variant)的数据集合,用于支持管理决策。

数据仓库体系结构通常含四个层次:数据源、数据存储和管理、数据服务、数据应用。

  • 数据源:是数据仓库的数据来源,含外部数据、现有业务系统和文档资料等;
  • 数据集成:完成数据的抽取、清洗、转换和加载任务,数据源中的数据采用ETL(Extract-Transform-Load)工具以固定的周期加载到数据仓库中。
  • 数据存储和管理:此层次主要涉及对数据的存储和管理,含数据仓库、数据集市、数据仓库检测、运行与维护工具和元数据管理等。
  • 数据服务:为前端和应用提供数据服务,可直接从数据仓库中获取数据供前端应用使用,也可通过OLAP(OnLine Analytical Processing,联机分析处理)服务器为前端应用提供负责的数据服务。
  • 数据应用:此层次直接面向用户,含数据查询工具、自由报表工具、数据分析工具、数据挖掘工具和各类应用系统。

传统数据仓库的问题

  • 无法满足快速增长的海量数据存储需求,传统数据仓库基于关系型数据库,横向扩展性较差,纵向扩展有限。
    这个本来就不是RDBMS的优势,横向扩展的时候分库分表,纵向扩展(扩展内存,CPU等)。
  • 无法处理不同类型的数据,传统数据仓库只能存储结构化数据,企业业务发展,数据源的格式越来越丰富。
  • 传统数据仓库建立在关系型数据仓库之上,计算和处理能力不足,当数据量达到TB级后基本无法获得好的性能。

Hive

Hive是建立在Hadoop之上的数据仓库,由Facebook开发,在某种程度上可以看成是用户编程接口,本身并不存储和处理数据,依赖于HDFS存储数据,依赖MR处理数据。有类SQL语言HiveQL,不完全支持SQL标准,如,不支持更新操作、索引和事务,其子查询和连接操作也存在很多限制。

Hive把HQL语句转换成MR任务后,采用批处理的方式对海量数据进行处理。数据仓库存储的是静态数据,很适合采用MR进行批处理。Hive还提供了一系列对数据进行提取、转换、加载的工具,可以存储、查询和分析存储在HDFS上的数据。

Hive与Hadoop生态系统中其他组件的关系

  • Hive依赖于HDFS存储数据,依赖MR处理数据;
  • Pig可作为Hive的替代工具,是一种数据流语言和运行环境,适合用于在Hadoop平台上查询半结构化数据集,用于与ETL过程的一部分,即将外部数据装载到Hadoop集群中,转换为用户需要的数据格式;
  • HBase是一个面向列的、分布式可伸缩的数据库,可提供数据的实时访问功能,而Hive只能处理静态数据,主要是BI报表数据,Hive的初衷是为减少复杂MR应用程序的编写工作,HBase则是为了实现对数据的实时访问。

Hive与传统数据库的对比

Hive 传统数据库
数据插入 支持批量导入,不可单条导入 支持单条和批量导入
数据更新 不支持 支持
索引 有限索引功能,不像RDBMS有键的概念,
可在某些列上建索引,加速一些查询操作。
创建的索引数据,会被保存在另外的表中
支持
分区 支持,Hive表示分区形式进行组织的,根据
“分区列”的值对表进行粗略划分,
加快数据的查询速度
支持,提供分区功能来改善大型表以及具有各
种访问模式的表的可伸缩性、可管理性,
以及提高数据库效率
执行延迟 高,构建在HDFS和MR之上,比传统数据库
延迟要高
低,传统SQL语句的延迟一般少于1秒,而HQL
语句延迟可达分钟级。
扩展性 好,基于Hadoop集群,有很好的横向扩展性 有限,RDBMS非分布式,横向扩展(分布式添
加节点)难实现,纵向扩展(扩展内存,CPU
等)也很有限

Hive的部署和应用

当前企业中部署的大数据分析平台,除Hadoop的基本组件HDFS和MR外,还结合使用Hive、Pig、HBase、Mahout,从而满足不同业务场景需求。

上图是企业中一种常见的大数据分析平台部署框架 ,在这种部署架构中:

  • Hive和Pig用于报表中心,Hive用于分析报表,Pig用于报表中数据的转换工作。
  • HBase用于在线业务,HDFS不支持随机读写操作,而HBase正是为此开发,可较好地支持实时访问数据。
  • Mahout提供一些可扩展的机器学习领域的经典算法实现,用于创建商务智能(BI)应用程序。

Hive系统架构

Hive主要由以下三个模块组成:

  • 用户接口模块,含CLI、HWI、JDBC、Thrift Server等,用来实现对Hive的访问。CLI是Hive自带的命令行界面;HWI是Hive的一个简单网页界面;JDBC、ODBC以及Thrift Server可向用户提供进行编程的接口,其中Thrift Server是基于Thrift软件框架开发的,提供Hive的RPC通信接口。
  • 驱动模块(Driver),含编译器、优化器、执行器等,负责把HiveQL语句转换成一系列MR作业,所有命令和查询都会进入驱动模块,通过该模块的解析变异,对计算过程进行优化,然后按照指定的步骤执行。
  • 元数据存储模块(Metastore),是一个独立的关系型数据库,通常与MySQL数据库连接后创建的一个MySQL实例,也可以是Hive自带的Derby数据库实例。此模块主要保存表模式和其他系统元数据,如表的名称、表的列及其属性、表的分区及其属性、表的属性、表中数据所在位置信息等。

喜欢图形界面的用户,可采用几种典型的外部访问工具:Karmasphere、Hue、Qubole等。

Hive工作原理

SQL语句转换成MapReduce作业的基本原理

用MapReduce实现连接操作

假设连接(join)的两个表分别是用户表User(uid,name)和订单表Order(uid,orderid),具体的SQL命令:

SELECT name, orderid FROM User u JOIN Order o ON u.uid=o.uid;

上图描述了连接操作转换为MapReduce操作任务的具体执行过程:

  • 首先,在Map阶段,
    • User表以uid为key,以name和表的标记位(这里User的标记位记为1)为value,进行Map操作,把表中记录转换生成一系列KV对的形式。比如,User表中记录(1,Lily)转换为键值对(1,<1,Lily>),其中第一个“1”是uid的值,第二个“1”是表User的标记位,用来标示这个键值对来自User表;
    • 同样,Order表以uid为key,以orderid和表的标记位(这里表Order的标记位记为2)为值进行Map操作,把表中的记录转换生成一系列KV对的形式;
  • 接着,在Shuffle阶段,把User表和Order表生成的KV对按键值进行Hash,然后传送给对应的Reduce机器执行。比如KV对(1,<1,Lily>)、(1,<2,101>)、(1,<2,102>)传送到同一台Reduce机器上。当Reduce机器接收到这些KV对时,还需按表的标记位对这些键值对进行排序,以优化连接操作;
  • 最后,在Reduce阶段,对同一台Reduce机器上的键值对,根据“值”(value)中的表标记位,对来自表User和Order的数据进行笛卡尔积连接操作,以生成最终的结果。比如键值对(1,<1,Lily>)与键值对(1,<2,101>)、(1,<2,102>)的连接结果是(Lily,101)、(Lily,102)。

用MapReduce实现分组操作

  • 首先,在Map阶段,对表Score进行Map操作,生成一系列KV对,其键为<rank, level>,值为“拥有该<rank, level>组合值的记录的条数”。比如,Score表的第一片段中有两条记录(A,1),所以进行Map操作后,转化为键值对(<A,1>,2);
  • 接着在Shuffle阶段,对Score表生成的键值对,按照“键”的值进行Hash,然后根据Hash结果传送给对应的Reduce机器去执行。比如,键值对(<A,1>,2)、(<A,1>,1)传送到同一台Reduce机器上,键值对(<B,2>,1)传送另一Reduce机器上。然后,Reduce机器对接收到的这些键值对,按“键”的值进行排序;
  • 在Reduce阶段,把具有相同键的所有键值对的“值”进行累加,生成分组的最终结果。比如,在同一台Reduce机器上的键值对(<A,1>,2)和(<A,1>,1)Reduce操作后的输出结果为(A,1,3)。

Hive中SQL查询转换成MR作业的过程

当Hive接收到一条HQL语句后,需要与Hadoop交互工作来完成该操作。HQL首先进入驱动模块,由驱动模块中的编译器解析编译,并由优化器对该操作进行优化计算,然后交给执行器去执行。执行器通常启动一个或多个MR任务,有时也不启动(如SELECT * FROM tb1,全表扫描,不存在投影和选择操作)

上图是Hive把HQL语句转化成MR任务进行执行的详细过程:

  • 由驱动模块中的编译器–Antlr语言识别工具,对用户输入的SQL语句进行词法和语法解析,将HQL语句转换成抽象语法树(AST Tree)的形式;
  • 遍历抽象语法树,转化成QueryBlock查询单元。因为AST结构复杂,不方便直接翻译成MR算法程序。其中QueryBlock是一条最基本的SQL语法组成单元,包括输入源、计算过程、和输入三个部分;
  • 遍历QueryBlock,生成OperatorTree(操作树),OperatorTree由很多逻辑操作符组成,如TableScanOperator、SelectOperator、FilterOperator、JoinOperator、GroupByOperator和ReduceSinkOperator等。这些逻辑操作符可在Map、Reduce阶段完成某一特定操作;
  • Hive驱动模块中的逻辑优化器对OperatorTree进行优化,变换OperatorTree的形式,合并多余的操作符,减少MR任务数、以及Shuffle阶段的数据量;
  • 遍历优化后的OperatorTree,根据OperatorTree中的逻辑操作符生成需要执行的MR任务;
  • 启动Hive驱动模块中的物理优化器,对生成的MR任务进行优化,生成最终的MR任务执行计划;
  • 最后,有Hive驱动模块中的执行器,对最终的MR任务执行输出。

Hive驱动模块中的执行器执行最终的MR任务时,Hive本身不会生成MR算法程序。它通过一个表示“Job执行计划”的XML文件,来驱动内置的、原生的Mapper和Reducer模块。Hive通过和ResourceManager通信来初始化MR任务,而不需直接部署在ResourceManager所在管理节点上执行。通常在大型集群中,会有专门的网关机来部署Hive工具,这些网关机的作用主要是远程操作和管理节点上的ResourceManager通信来执行任务。Hive要处理的数据文件常存储在HDFS上,HDFS由名称节点(NameNode)来管理。

Hive HA基本原理

在实际应用中,Hive也暴露出不稳定的问题,在极少数情况下,会出现端口不响应或进程丢失问题。Hive HA(High Availablity)可以解决这类问题。

在Hive HA中,在Hadoop集群上构建的数据仓库是由多个Hive实例进行管理的,这些Hive实例被纳入到一个资源池中,由HAProxy提供统一的对外接口。客户端的查询请求,首先访问HAProxy,由HAProxy对访问请求进行转发。HAProxy收到请求后,会轮询资源池中可用的Hive实例,执行逻辑可用性测试。

  • 如果某个Hive实例逻辑可用,就会把客户端的访问请求转发到Hive实例上;
  • 如果某个实例不可用,就把它放入黑名单,并继续从资源池中取出下一个Hive实例进行逻辑可用性测试。
  • 对于黑名单中的Hive,Hive HA会每隔一段时间进行统一处理,首先尝试重启该Hive实例,如果重启成功,就再次把它放入资源池中。

由于HAProxy提供统一的对外访问接口,因此,对于程序开发人员来说,可把它看成一台超强“Hive”。

Hive metastore三种配置方式

Hive的meta数据支持以下三种存储方式,其中两种属于本地存储,一种为远端存储。远端存储比较适合生产环境。Hive官方wiki详细介绍了这三种方式,链接为:https://cwiki.apache.org/confluence/display/HADOOP2/Hive/AdminManual/MetastoreAdmin

本地derby

这种方式是最简单的存储方式,只需要在hive-site.xml做如下配置便可

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
	<property>
	  <name>javax.jdo.option.ConnectionURL</name>
	  <value>jdbc:derby:;databaseName=metastore_db;create=true</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionDriverName</name>
	  <value>org.apache.derby.jdbc.EmbeddedDriver</value>
	</property>
	 
	<property>
	  <name>hive.metastore.local</name>
	  <value>true</value>
	</property>
	 
	<property>
	  <name>hive.metastore.warehouse.dir</name>
	  <value>/user/hive/warehouse</value>
	</property>
</configuration>

注:使用derby存储方式时,运行hive会在当前目录生成一个derby文件和一个metastore_db目录。这种存储方式的弊端是在同一个目录下同时只能有一个hive客户端能使用数据库,否则会提示如下错误

hive> show tables;
FAILED: Error in metadata: javax.jdo.JDOFatalDataStoreException: Failed to start database 'metastore_db', see the next exception for details.
NestedThrowables:
java.sql.SQLException: Failed to start database 'metastore_db', see the next exception for details.
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask

本地mysql

这种存储方式需要在本地运行一个mysql服务器,并作如下配置(下面两种使用mysql的方式,需要将mysql的jar包拷贝到$HIVE_HOME/lib目录下)。

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
	<property>
	  <name>hive.metastore.warehouse.dir</name>
	  <value>/user/hive_remote/warehouse</value>
	</property>
	 
	<property>
	  <name>hive.metastore.local</name>
	  <value>true</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionURL</name>
	  <value>jdbc:mysql://localhost/hive_remote?createDatabaseIfNotExist=true</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionDriverName</name>
	  <value>com.mysql.jdbc.Driver</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionUserName</name>
	  <value>hive</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionPassword</name>
	  <value>password</value>
	</property>
</configuration>

远端mysql

这种存储方式需要在远端服务器运行一个mysql服务器,并且需要在Hive服务器启动meta服务。

这里用mysql的测试服务器,ip位192.168.1.214,新建hive_remote数据库,字符集位latine1

<property>
  <name>hive.metastore.warehouse.dir</name>
  <value>/user/hive/warehouse</value>
</property>
 
<property>
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:mysql://192.168.1.214:3306/hive_remote?createDatabaseIfNotExist=true</value>
</property>
 
<property>
  <name>javax.jdo.option.ConnectionDriverName</name>
  <value>com.mysql.jdbc.Driver</value>
</property>
 
<property>
  <name>javax.jdo.option.ConnectionUserName</name>
  <value>hive</value>
</property>
 
<property>
  <name>javax.jdo.option.ConnectionPassword</name>
  <value>password</value>
</property>
 
<property>
  <name>hive.metastore.local</name>
  <value>false</value>
</property>
 
<property>
  <name>hive.metastore.uris</name>
  <value>thrift://192.168.1.188:9083</value>
</property>

注:这里把hive的服务端和客户端都放在同一台服务器上了。服务端和客户端可以拆开,将hive-site.xml配置文件拆为如下两部分

服务端配置文件

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
	<property>
	  <name>hive.metastore.warehouse.dir</name>
	  <value>/user/hive/warehouse</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionURL</name>
	  <value>jdbc:mysql://192.168.1.214:3306/hive_remote?createDatabaseIfNotExist=true</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionDriverName</name>
	  <value>com.mysql.jdbc.Driver</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionUserName</name>
	  <value>root</value>
	</property>
	 
	<property>
	  <name>javax.jdo.option.ConnectionPassword</name>
	  <value>test1234</value>
	</property>
</configuration>

客户端配置文件

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
 
	<property>
	  <name>hive.metastore.warehouse.dir</name>
	  <value>/user/hive/warehouse</value>
	</property>
	 
	<property>
	  <name>hive.metastore.local</name>
	  <value>false</value>
	</property>
	 
	<property>
	  <name>hive.metastore.uris</name>
	  <value>thrift://192.168.1.188:9083</value>
	</property>
 
</configuration>

启动hive服务端程序

$ hive --service metastore 

客户端直接使用hive命令即可

root@my188:~$ hive 
Hive history file=/tmp/root/hive_job_log_root_201301301416_955801255.txt
hive> show tables;
OK
test_hive
Time taken: 0.736 seconds
hive>

Hive中MetaServer与HiveServer2的应用

在hive中有metaServer与hiveServer2两种服务,看了好多文章说这两个的区别,文章内容有对有错,不够全面,故在这里好好总结一下。

首先,下面这个hive构架图,我们一定不陌生,它反应出hive有哪些组件结构

当然下面的图是hadoop1的部分,现在JobTracker是Yarn了
上面的部分是访问Hive的三个入口,

  • 1: 直接Cli
  • 2: 通过JDBC
  • 3: webUI

当我们要连接Hive进行操作时,首先必须是安装了,安装hive很简单,直接在conf/hive-site配置存放Hive元数据的连接信息,通常是用mysql,如下:

<property>
      <name>javax.jdo.option.ConnectionURL</name>
      <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
      <name>javax.jdo.option.ConnectionDriverName</name>
      <value>com.mysql.jdbc.Driver</value>
</property>
<property>
      <name>javax.jdo.option.ConnectionUserName</name>
      <value>root</value>
</property>
<property>
      <name>javax.jdo.option.ConnectionPassword</name>
      <value>root</value>
</property>

这样配置好后,在hive的lib里加入Mysql JDBC 驱动后,我们就可以通过 bin/hive的方式连接hive客户端,请求数据。如下图:

这样在大多数公司,特别是小公司小集群里基本是这样操作的,当然我们公司也是这样的,这样本身没有错误.
但我们看一下上面的配置,这样是不是把连接数据库的信息全泄露了,你可能会说,大家都是同公司的大数据部分,还有各种权限,泄露也无所谓,但我们想一下,在一个大的公司里,大数据平台是几个部门共用的,这样会有多台hive cli连接mysql,这样泄露mysql的信息的风险还是挺大的.
另一方面,比如我们元数据Mysql库无法启动,我们要替换从库时,或者我们要移植元数据到另一台机器上时,那么我们这么多的hive cli是不是全要修改一遍....

那么这时我们Hive的另一个组件出场了,它就是MetaStoreServer

启动:nohup $HIVE_HOME/bin/hive –metastore &

如图,我们在Hive cli与mysql中间是不是启动一个MetaStoreServer,
这样我们的Hive cli就不需要连接Mysql,直接连接这个MetaStoreServer不就行了吗,
在hive-site.xml只要简单的配置一下:

<property>
    <name>hive.metastore.uris</name>
    <value>thrift://xxxxxx:9083</value>
</property>

这样我就通过metaserver取得了元数据的信息对吧
当然上面的图只是一个MetaStoreServer,存在单点问题,但我们完全可以配置两个或者多个MetaStoreServer,就实现了负载均衡与容错的功能了,如下面的配置

<property>
	<name>hive.metastore.uris</name>
	<value>thrift://dw1:9083,thrift://dw2:9083</value>
</property>
posted @ 2020-04-07 15:28  江舟  阅读(450)  评论(0)    收藏  举报