Hive


[toc]

Hive概述

什么是Hive

  • 由Facebook开源用于解决海量结构化日志的数据统计;

  • 是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射成一张表,并提供类似SQL查询功能

  • 构建在Hadoop之上的数据仓库:使用HQL作为查询接口、使用HDFS存储、使用MapReduce计算

  • 支持UDF,自定义存储格式

  • 适合离线数据处理

表的类型

在Hive中创建表时,默认情况下Hive负责管理数据。这意味这Hive把数据移入它的“仓库目录”(warehouse directory)。创建一个外部表,让Hive到仓库目录以外的位置访问数据。

外部表

创建表时需要指明外部数据的位置,EXTERNAL关键字,Hive指导数据并不是由自己管理,一次不会把数据移动到自己的仓库目录;丢弃外部表时,Hive不会碰数据,只会删除元数据。

CREATE EXTERNAL TABLE external_table(dummy STRING)
LOCATION '/user/tom/external_table';

LOAD DATA LOCAL INPATH 'input/hive/partitions/file1' INTO TABLE external_table;
内部(托管)表
CREATE  TABLE managed_table(dummy STRING)
LOAD DATA LOCAL INPATH 'input/hive/partitions/file1' INTO TABLE managed_table;
分区表

Hive把表组织成分区,这是一种根据分区列的值对表进行粗略划分的机制,使用分区可以加快数据分片的查询速度。一个表可以以多个维度来进行分区(如下:使用PARTITIONED BY 指定分区,根据dt进行分区外,进一步根据country对每个分区进行子分区);PARTITIONED BY子句中的列定义是表中正式的列(分区列),但是数据文件并不包含这些列的值,因为它们源于目录名。

CREATE TABLE logs(ts BIGINT,line STRING)
PARTITIONED BY (dt STRING,country STRING)

在加载数据到分区表的时候,需要显示指定分区值:

LOAD DATA LOCAL INPATH 'input/hive/partitions/file1'
INTO TABLE logs
PARTITION(dt='2020-01-01',country='CN')

在文件系统级别,分区只是表目录下嵌套的子目录

分桶表

表或分区可以进一步分为桶;为数据提供额外的结构以获得更高效的查询处理高效使用“取样”/"采样",如下,使用id来确定如何划分桶(Hive对值进行哈希并将结果除以桶的个数取余数)

CREATE TABLE bucketed_users(id INT,name STRING)
CLUSTERED BY (id) INTO 4 BUCKETS;

将桶中的数据根据一个或多个列进行排序

CREATE TABLE bucketed_users(id INT,name STRING)
CLUSTERED BY (id) SORTED BY (id ASC) INTO 4 BUCKETS;

与分区不同的是,分区依据的不是真实数据表文件的列,而是我们指定的伪列;但是分桶是依据数据表中真实的列而不是伪列。

Hive 严格模式

防止用户执行那些可能产生意想不到的不好的效果的查询:即某些查询在严格模式下无法执行,通过设置hive.mapred.mode=strict可以限制以下3中类型的查询:

  • 带有分区表的查询:在一个分区表执行hive,where语句中必须包含分区字段过滤条件,否则不能执行;因为数据量太大;
  • 带有orderby的查询:使用了orderby的查询,必须要有limit语句;
  • 限制笛卡尔积的查询。

Hive 排序关键字

  • order by :对输入做全局排序,因此只有一个reduce(多个reduce无法保证全局有序),然而当输入规模较大时,消耗较长的计算时间;
  • sort by:不是全局排序,其在数据进入reduce前完成排序,如果使用sort by排序,并设置mapred.reduce.task>1,只会保证每个reduce的输出有序,不会保证全局有序;
  • distribute by:控制在map端如何拆分数据给reduce端,sort by为每一个reduce产生一个排序文件;distribute by经常和sort by配合使用。
  • cluster by:具有distribute by和sort by的组合功能,但只能升序排序

Hive的join底层实现

Common Join

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会默认把执行Common Join,即在Reduce阶段完成join。整个过程包含Map、Shuffle、Reduce阶段。

  • map

    读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;Map输出的value为join之后所关心的(select或者where中需要用到的)列,同时在value中还会包含表的Tag;

  • shuffle

    根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中。

  • reduce

    根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

Map Join

在map端进行join,节省了shuffle阶段要进行的大量数据传输,从而起到优化作用;MapJoin通常用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数hive.mapjoin.smalltable.filesize来决定,默认值为25M。满足条件的话Hive在执行时候会自动转化为MapJoin

Hive 数据倾斜

  • 产生的原因

    key分布不均匀、业务数据特性、建表问题、某些SQL语句本身就有数据倾斜问题

  • 解决

    • 参数调整

      Map端聚合;有数据倾斜的时候进行负载均衡

    • join

Hive 性能调优

  • 设置合理的map和reduce task的任务

  • 合理利用分区和分桶

  • join优化

    优先过滤再进行Join操作,最大限度的减少参与join的数据量;

    小表join大表,最好启动map join;

    join on的条件相同的话,最好放入同一个job,并且join表的排列顺序从小到大;

    将条目少的表/子查询放在join操作符的左边,因为会被加载到内存

    防止数据倾斜

  • group by 优化

  • 启动本地模式:数据量少的时候,没必要去执行分布式协调计算

  • 并行执行:让多个并不互相依赖stage(job)并发执行;

  • 设置合理的压缩

下载与安装

  • Apache download mirrors上下载;

  • 解压$ tar -xzvf hive-x.y.z.tar.gz

  • 配置环境变量:

     #设置HIVE_HOME指向安装目录
     $ cd hive-x.y.z
     $ export HIVE_HOME={{pwd}}
     #在PATH中添加$HIVE_HOME/bin
     $ export PATH=$HIVE_HOME/bin:$PATH

基本配置

#hive-log4j.properties
#日志目录需要提前创建
hive.log.dir=/opt/modules/hive-2.1.0/logs
#hive-env.sh
HADOOP_HOME=/opt/modules/hadoop-2.6.0
HBASE_HOME=/opt/modules/hbase-1.0.0-cdh5.4.0
# Hive Configuration Directory can be controlled by:
export HIVE_CONF_DIR=/opt/modules/hive-2.1.0/conf

运行Hive

  • 前提条件:

    you must use below HDFS commands to create/tmp and/user/hive/warehouse (aka hive.metastore.warehouse.dir) and set them chmod g+w before you can create a table in Hive.

    $ $HADOOP_HOME/bin/hadoop fs -mkdir       /tmp
    $ $HADOOP_HOME/bin/hadoop fs -mkdir       /user/hive/warehouse
    $ $HADOOP_HOME/bin/hadoop fs -chmod g+w   /tmp
    $ $HADOOP_HOME/bin/hadoop fs -chmod g+w   /user/hive/warehouse

    若是使用mysql存储元数据还需要启动mysql服务

  • bin/hive运行

    启动Hive的shell环境,与Hibe进行交互;

    注意:hive 1.x版本时,不需要进行初始化操作,Hive第一次启动的时候会自动进行初始化,但不会生成所有的元数据信息表,只会初始化必要的部分,在之后的时候过程中会自动创建;当使用hive2.x版本时,必须手动初始化元数据库。默认情况下,Hive的元数据保存在了内嵌的derby数据库里,需要在Hive安装目录的bin目录下执行:

    ./schematool -initSchema -dbType mysql(根据实际情况填写,因为我安装的是mysql,故。。)

    #若没有进行初始化则会出现如下异常:
    Exception in thread "main" java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: org.apache.hadoop.hive.ql.metadata.HiveException: MetaException(message:Hive metastore database is not initialized. Please use schematool (e.g. ./schematool -initSchema -dbType ...) to create the schema. If needed, don't forget to include the option to auto-create the underlying database in your JDBC connection string (e.g. ?createDatabaseIfNotExist=true for mysql))

常见操作

#创建一个表:ROW FORMAT DELIMITED---规定了数据格式,
#FIELDS TERMINATED BY '\t':列间隔为一个制表符,即tab
#LINES TERMINATED BY '\n':行间隔'\n',即换行 
#声明一个stu2表,包括id、name两列,指明每一列的数据类型分别为int、string;数据文件的每一行是由制表符分割的文本,Hive按照这一格式读取数据。
CREATE TABLE stu2(id INT,name STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;
#加载数据到表中,注意加载数据的格式是否符合表创建时的要求
#OVERWRITE:告诉Hive删除表对应目录中已有的所有文件,不写的话Hive就简单地把新的文件加入目录(若该目录下有同名的文件,则替换原有同名文件)
load data local inpath '/opt/datas/stu.txt' [OVERWRITE] into table stu2;
#打印hive启动过程中的log
$ ./bin/hive -hiveconf hive.root.logger=DEBUG,console
#进入hive查看有哪些表
show tables;

Hive 与 MySQL

为什么与mysql进行整合

默认情况下,Hive元数据保存在内嵌的Derby数据库中,只能允许一个会话连接,只适合简单的测试。实际生产环境中不使用,为了支持多用户会话,则需要一个独立的元数据库,使用MySQL作为元数据库,Hive内部对MySQL提供了很好的支持。

相关配置文件

默认是没有hive-site.xml文件的,需要自己创建。

#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:mysql://bigdata-pro01.bigDAta.com/metastore?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>123456</value>
  </property>
</configuration>

Hive与HBase整合

HBase和Hive的区别

HBase Hive
类型 列式数据库 数据仓库
内部机制 数据库引擎 MapReduce
增删改查 都支持 只支持导入和查询
Schema 只需要预先定义列族,不需要具体到列,列可以动态修改 需要预先定义表格
应用场景 实时 离线处理
特点 以K-V形式存储 类SQL

整合后的使用场景:

  • 通过Hive把数据加载到HBase中,数据源可以是文件也可以是Hive中的表。
  • 通过整合,让HBase支持JOIN、GROUP等SQL查询语法。
  • 通过整合,不仅可完成HBase的数据实时查询,也可以使用Hive查询HBase中的数据完成复杂的数据分析。

Hive和HBase整合的实现是利用两者本身对外的API接口互相通信完成的,其具体工作是交由Hive的lib目录下的hive-hbase-handler-*.jar来实现。

整合过程

  • 首先在hive-site.xml文件中添加

    #不需要写端口号
    <property>
        <name>hbase.zookeeper.quorum</name>   
        <value>bigdata-pro01.bigDAta.com,bigdata-pro02.bigDAta.com,bigdata-pro03.bigDAta.com</value>
      </property>
  • 将 HBase中的部分jar包拷贝到Hive中,如果两者都是CDH版本,就不需要进行拷贝;若hive安装时自带了以下jar包,将其删除。

    export HBASE_HOME=/opt/modules/hbase-1.0.0-cdh5.4.0
    export HIVE_HOME=/opt/modules/hive-2.1.0
    
    ln -s $HBASE_HOME/lib/hbase-server-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-server-1.0.0-cdh5.4.0.jar
    
    ln -s $HBASE_HOME/lib/hbase-client-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-client-1.0.0-cdh5.4.0.jar
    
    ln -s $HBASE_HOME/lib/hbase-protocol-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-protocol-1.0.0-cdh5.4.0.jar 
    
    ln -s $HBASE_HOME/lib/hbase-it-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-it-1.0.0-cdh5.4.0.jar 
    
    ln -s $HBASE_HOME/lib/htrace-core-3.0.4.jar $HIVE_HOME/lib/htrace-core-3.0.4.jar
    
    ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-hadoop2-compat-1.0.0-cdh5.4.0.jar 
    
    ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-hadoop-compat-1.0.0-cdh5.4.0.jar
    
    ln -s $HBASE_HOME/lib/high-scale-lib-1.1.1.jar $HIVE_HOME/lib/high-scale-lib-1.1.1.jar 
    
    ln -s $HBASE_HOME/lib/hbase-common-1.0.0-cdh5.4.0.jar $HIVE_HOME/lib/hbase-common-1.0.0-cdh5.4.0.jar

    与hbase集成过程中,若lib目录下的相关jar未更换,在Hive创建外部表与HBase进行关联时,会出现regionserver挂掉了,以及报以下错误:

    FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=36, exceptions:
    Tue Apr 14 12:35:30 EDT 2020, null, java.net.SocketTimeoutException: callTimeout=60000, callDuration=68408: row 'weblogs,,' on table 'hbase:meta' at region=hbase:meta,,1.1588230740, hostname=bigdata-pro03.bigDAta.com,60020,1586881704857, seqNum=0
        ------------
    Caused by: java.net.SocketTimeoutException: callTimeout=60000, callDuration=68408: row 'weblogs,,' on table 'hbase:meta' at region=hbase:meta,,1.1588230740, hostname=bigdata-pro03.bigDAta.com,60020,1586881704857, seqNum=0
        --------------
    Caused by: java.net.ConnectException: Connection refused

Hive的优点及应用场景


Manba_girl: Mamba_girl
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Mamba_girl !
  目录