文章目录
1 hive基本概念
hive是一个基于hadoop的数据仓库工具,将结构化数据映射为一张表,提供类SQL查询功能。这里可以理解为它架构在Hadoop之上,可以将类sql语句(hive支持的HQL)转换为MapReduce任务进行运行,就可以避免复杂的mapreduce编程。
hive的一些性质:
- hive处理的数据存储到HDFS上
- Hive分析数据底层实现是MapReduce
- 执行程序运行在Yarn上
- hive属于客户端,没有集群的概念,不同的hive程序可以访问相同的数据,但是是独立访问的。
1.1 hive优缺点
(1)优点:
- 操作采用类SQL语法,提供快速开发的能力
- 避免了写Mapreduce,减少开发人员的学习成本
- hive执行延迟比较高,适用于对实时性要求不高的场合
- hive支持用户滴定函数,用户可以根据自己的需求来实现自己的函数
(2)缺点
- hive的HQL表达能力有限。(无法运算迭代算法、不擅长数据挖掘)
- hive的效率比较低。(自动生成的Mapreduce作业不够智能化,调优困难)
1.2 hive架构原理
一个一个解释图中的模块:
1)用户接口:Client
负责CLI(Command-line interface)、JDBC/ODBC(jdbc访问hive)、WEBUI(浏览器访问hive)。
2)元数据:MetaStore
元数据包括:表名、表所属的数据库、表的拥有者、列/分区字段、表的类型、表的数据所在目录。
3)hadoop
使用HDFS存储、使用mapreduce进行计算。
4)驱动器:driver
- 解析器:将SQL转换为抽象语法树(AST),对AST进行初步分析(表是否存在、字段是否存在、SQL语义是否有误)。
- 编译器:将AST编译成逻辑执行计划
- 优化器:对逻辑执行计划进行优化
- 执行器:把逻辑执行计划转换为可以运行的物理计划。
综合来看,hive一次任务的执行就是:hive收到客户端用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore)
,将这些指令翻译成MapReduce,提交到hadoop中执行,最后将执行结果输出到用户交互接口。
1.3 hive和数据库比较
- hive支持的HQL与SQLyoudianchabie1
- hive不建议对数据进行改写,所有数据都是加载时就确定好的,数据库中的数据需要经常修改。
- hive执行需要扫描整个表,延迟比较高。由于其是并行计算的,所以处理大数据量时具有优势
- hive可以支撑很大规模的数据,数据库支持的数据规模较小。
2 hive安装
安装过程逻辑如上图,先将hive装上,再安装MySQL,然后将hive的元数据配置到MySQL上,然后介绍hive的三种访问方式,最后简单介绍一下hive的交互命令。
2.1 hive安装
下载地址:https://dlcdn.apache.org/hive/hive-3.1.2/
- 上传到linux目录下、解压、查看hive的目录结构
- 添加环境变量:
sudo vim /etc/profile.d/my_env.sh
,向其中添加HIVE_HOME的内容。source /etc/profile
使得环境变量生效。 - 初始化元数据:
bin/schematool -dbType derby -initSchema
如果初始化的时候报错:
in thread "main"java.lang.NoSuchMethodError:com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
解决方案参考: http://www.shangdixinxi.com/detail-1151470.html
安装完之后启动一下:
- 先启动hadoop再使用hive:
bin/hive
- 使用hive:创建表、插入操作、查询操作;
查询:
在hadoop默认路径下就已经有数据了:/user/hive/warehouse/test
但是元数据是看不到的,因为存在了derby这个数据库中,除了源数据查看不方便,这个数据库只能不能同时允许多个用户进行访问。所以要换乘mysql。
2.2 MySQL安装
1)检查系统是否安装过MySQL,一般系统会自动安装一个,需要把它卸载:
rpm -qa|grep mariadb
sudo rpm -e --nodeps mariadb-libs
2)mysql下载安装、解压、执行rpm安装:
具体可以参考这篇文章:https://blog.csdn.net/weixin_43451430/article/details/115553108
按照上面文章到修改root密码之后,然后配置修改mysql库下表中root用户允许任意ip连接:
我们可以看到运行前后,这个user表的变化,说明任何ip用户都可以登录访问这个Mysql了。
开始用Navicat访问链接试试。
2.3 hive元数据配置到MySQL
1)将MySQL的JDBC驱动拷贝到Hive的lib目录下。jdbc驱动下载介绍:https://blog.csdn.net/HDZ1821/article/details/104373946
2)配置Metastore到MySQL
- 新建hive-site.xml
vim $HIVE_HOME/conf/hive-site.xml
并在hive-site.xml文件中添加以下内容:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- jdbc 连接的URL -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop100:3306/metastore?useSSL=false</value>
</property>
<!-- jdbc 连接的Driver-->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- jdbc 连接的username-->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<!-- jdbc 连接的password -->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<!-- Hive 元数据存储版本的验证 -->
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
<!--元数据存储授权-->
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
<!-- Hive 默认在HDFS 的工作目录 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>
- 登录Mysql数据库、新建hive元数据库(注意这里新建的数据库就是第一步配置文件中的数据库名)
mysql> create database metastore;
mysql> quit;
- 初始化hive元数据库。
schematool -initSchema -dbType mysql -verbose
总结一下上面这三步:就是新建配置文件,覆盖掉hive的默认文件,这个配置了元数据存在哪个数据库、用啥用户、驱动和密码来访问这个数据库、这些数据是存在hdfs哪个文件目录下等信息。配置完之后就可以通过再次启动hive来进行测试了。
通过以上测试,我们可以发现多个客户端可以使用同一个hive,并进行操作。这在不配置MySQL前是不行的,因为hive默认的元数据库derby不与其他客户端共享数据。
2.4 hive的访问
(1)直接访问:类似于上面测试的内容:直接通过bin/hive
启动,然后进行操作。
(2)使用元数据服务的方式访问hive:
1)为啥需要使用元数据服务方式?
希望通过第三方通过服务的方式访问hive。客户端连接metastore服务,metastore再去连接MySQL数据库来存取元数据。有了metastore服务,就可以有多个客户端同时连接,而且这些客户端不需要知道MySQL数据库的用户名和密码,只需要连接metastore 服务即可。
2)怎么配置元数据服务方式?
①在hive-site.xml文件中添加配置信息:
<property>
<name>hive.metastore.uris</name>
<value>thrift://hadoop100:9083</value>
</property>
②启动metastore:这是一个后端进程、启动之后需要再开一个shell窗口启动
hive --service metastore
开启之后就有一个RunJar的进程。
(3)使用JDBC方式访问hive:
这里为了好理解JDBC访问hive,我们必须要了解元数据服务metastore:先贴个链接
本文介绍的主要是本地模式的JDBC访问,即:
MetaStore 服务仍然和 Hive 服务运行在同一个进程中,但连接的却是另一个进程中运行的数据库,在同一台机器上或者远程机器上。此时如果客户端要访问Hive,走的过程如下图所示:
此时client通过Thrift Server来访问hive,简略图如下图所示。
接下来介绍如何配置
(1)在hive-site.xml文件中添加如下配置信息
<!-- 指定hiveserver2 连接的host -->
<property>
<name>hive.server2.thrift.bind.host</name>
<value>hadoop100</value>
</property>
<!-- 指定hiveserver2 连接的端口号 -->
<property>
<name>hive.server2.thrift.port</name>
<value>10000</value>
</property>
(2)启动metastore(前提是启动了metastore)
bin/hive --service hiveserver2
(3)启动beeline客户端
bin/beeline -u jdbc:hive2://hadoop100:10000 -n hhh
这里容易报错:Error: Could not open client transport with JDBC Uri: jdbc:hive2://hadoop102:10000: Failed to open new session: java.lang.RuntimeException
是因为在core.site.xml缺少配置文件,代理对象设置为自己的用户名,解决办法详见。
启动之后见到下面这里的东西就算成功了:
启动之后的分析:
(1)启动metastore:hive --service metastore
是前台进程
启动hiveserver2:bin/hive --service hiveserver2
也是前台进程。
启动hiveserver2之后,发现有两个RunJar进程:
然后分别用ps -aux | grep 进程号
分析这两个RunJar具体信息,如下图所示:
其中一个是HiveServer2,一个是HiveMetaStore。显然,前端进程不方便(因为一直要保持开启进程活着,显然切换为后端进程比较好)。开起了上面的任意进程,就不能通过bin/hive
进行启动了。
(2)编写hive服务启动的脚本:
写在前面,nohup放在命令开头,表示不挂起,也就是关闭程序终端也能够继续保持运行状态。
nohup hive --service metastore 2>&1 &
nohup hive --service hiveserver2 2>&1 &
2>&1
: 表示将错误重定向到标准输出上&
: 放在命令结尾,表示后台运行
一般会组合使用: nohup [xxx 命令操作]> file 2>&1 &
,表示将xxx 命令运行的结
果输出到file 中,并保持命令启动的进程在后台运行。
#!/bin/bash
HIVE_LOG_DIR=$HIVE_HOME/logs
if [ ! -d $HIVE_LOG_DIR ]
then
mkdir -p $HIVE_LOG_DIR
fi
#检查进程是否运行正常,参数1 为进程名,参数2 为进程端口
function check_process()
{
pid=$(ps -ef 2>/dev/null | grep -v grep | grep -i $1 | awk '{print $2}')
ppid=$(netstat -nltp 2>/dev/null | grep $2 | awk '{print $7}' | cut -d '/' -f 1)
echo $pid
[[ "$pid" =~ "$ppid" ]] && [ "$ppid" ] && return 0 || return 1
}
function hive_start()
{
metapid=$(check_process HiveMetastore 9083)
cmd="nohup hive --service metastore >$HIVE_LOG_DIR/metastore.log 2>&1 &"
[ -z "$metapid" ] && eval $cmd || echo "Metastroe 服务已启动"
server2pid=$(check_process HiveServer2 10000)
cmd="nohup hiveserver2 >$HIVE_LOG_DIR/hiveServer2.log 2>&1 &"
[ -z "$server2pid" ] && eval $cmd || echo "HiveServer2 服务已启动"
}
function hive_stop()
{
metapid=$(check_process HiveMetastore 9083)
[ "$metapid" ] && kill $metapid || echo "Metastore 服务未启动"
server2pid=$(check_process HiveServer2 10000)
[ "$server2pid" ] && kill $server2pid || echo "HiveServer2 服务未启动"
}
case $1 in
"start")
hive_start
;;
"stop")
hive_stop
;;
"restart")
hive_stop
sleep 2
hive_start
;;
"status")
check_process HiveMetastore 9083 >/dev/null && echo "Metastore 服务运行正常" || echo "Metastore 服务运行异常"
check_process HiveServer2 10000 >/dev/null && echo "HiveServer2 服务运行正常" || echo "HiveServer2 服务运行异常"
;;
*)
echo Invalid Args!
echo 'Usage: '$(basename $0)' start|stop|restart|status'
;;
esac
赋予权限:
chmod +x $HIVE_HOME/bin/hiveservices.sh
上面的代码也挺简单的,他通过服务名和端口号来查询是否有这个服务,再让它挂起或者关闭。
总结
有时候,你的选择真的很少,继续前行吧。