[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