Hive基本概念

什么是Hive

Hive简介

  • Hive:由Facebook开源用于解决海量结构化日志的数据统计工具。
  • Hive:是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。

    Hive本质

    将HQL转化成MapReduce程序

  • image.png

  • Hive处理的数据存储在HDFS
  • Hive分析数据底层的实现是MapReduce
  • 执行程序运行在Yarn上

    Hive的优缺点

    优点

  • 操作接口采用类SQL语法,提供快速开发的能力

  • 避免了去写MapReduce,减少开发人员的学习成本
  • Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要去不高的场合
  • Hive的优势在于处理大数据,对于处理小数据没有优势,因为Hive的执行延迟比较高
  • Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数

    缺点

    Hive的HQL表达能力有限

  • 迭代式算法无法表达

  • 数据挖掘方面不擅长,由于MapReduce数据处理流程的限制,效率更高的算法却无法实现

    Hive的效率比较低

  • Hive自动生成的MapReduce作业,通常情况下不够智能化

  • Hive调优比较困难,粒度较粗

    Hive架构原理

    image.png

    用户接口:Client

  • CLI(command-line interface)、JDBC/ODBC(jdbc访问hive)、WEBUI(浏览器访问hive)

    元数据:Meta store

  • 元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等。

  • 默认存在自带的derby数据库中,推荐使用MySQL存储Meta store

    Hadoop

  • 使用HDFS进行存储,使用MapReduce进行计算

    驱动器:Driver

  • 解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误

  • 编译器(Physical Plan):将AST编译生成逻辑执行计划
  • 优化器(Query Optimizer):对逻辑执行计划进行优化
  • 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对Hive来说买就送MR/Spark

    Hive运行机制

    image.png

  • Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(Meta store),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后将执行返回的结果输出到用户交互接口。

    Hive和数据库比较

  • 由于Hive采用了类似SQL的查询语义HQL(Hive Query Language),因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语义,再无类似之处。本文将从多个方面来阐述Hive和数据库的差异。数据库可以用在Online的应用中,但是Hive是为数据仓库而设计的,清楚这一点,有助于从应用角度理解Hive的特性。

    查询语言

  • 由于SQL被广泛的应用在数据仓库中,因此,专门针对Hive的特性设计了类SQL的查询语言HQL。熟悉SQL开发的开发者可以很方便的使用Hive进行开发。

    数据更新

  • 由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不建议对数据的改写,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用INSERT INTO ... VALUES添加数据,使用 UPDATE ... SET修改数据。

    执行延迟

  • Hive在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致Hive执行延迟高的因素是MapReduce框架。由于MapReduce本身具有较高的延迟,因此在利用MapReduce执行Hive查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据的处理能力的时候,Hive的并行计算显然能体现出优势。

    数据规模

  • 由于Hive建立在集群上并可以利用MapReduce进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。

    Hive安装

    Hive安装地址

    Hive官网地址

    http://hive.apache.org/

    文档查看地址

    https://cwiki.apache.org/confluence/display/Hive/GettingStarted

    下载地址

    http://archive.apache.org/dist/hive/

    github地址

    https://github.com/apache/hive

    Hive安装部署

    安装Hive

  • apache-hive-3.1.2-bin.tar.gz上传到linux的 /opt/software目录下

  • 解压 apache-hive-3.1.2-bin.tar.gz/opt/module/目录下
    • tar -zxvf /opt/software/apache-hive-3.1.2-bin.tar.gz -C /opt/module/
  • 修改 apache-hive-3.1.2-bin的名称为hive
    • mv /opt/module/apache-hive-3.1.2-bin/ /opt/module/hive
  • 修改 /etc/profile.d/my_env.sh 添加环境变量
    • vi /etc/profile.d/my_env.sh
  • 添加内容
    • #HIVE_HOME
    • export HIVE_HOME=/opt/module/hive
    • export PATH=$PATH:$HIVE_HOME/bin
  • 更新环境变量
    • source /etc/profile
  • 解决日志jar包冲突
    • mv $HIVE_HOME/lib/log4j-slf4j-impl-2.10.0.jar $HIVE_HOME/lib/log4j-slf4j-impl-2.10.0.bak
  • 初始化元数据库

    • [root@hadoop102 hive]# bin/schematool -dbType derby -initSchema

      启动并使用Hive

      启动Hive

      [root@hadoop102 hive]# bin/hive

      使用Hive

      1. show databases;
      2. show tables;
      3. create table test(id int);
      4. insert into test values(1);
      5. select * from test;

      Mysql安装

      检查当前系统是否安装过MySQL

  • rpm -qa|grep mariadb

  • rpm -qa|grep mysql
  • rpm -qa|grep -i mysql
  • 卸载

    • rpm -e --nodeps mariadb-libs

      将mysql安装包拷贝到 /opt/software目录下

      拷贝mysql连接的jar到hive目录下

  • cp /opt/software/mysql-connector-java-5.1.27-bin.jar /opt/module/hive/lib/

    解压mysql安装包

  • tar -xf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar

    依次执行下面的安装

  • rpm -ivh mysql-community-common-5.7.28-1.el7.x86_64.rpm

  • rpm -ivh mysql-community-libs-5.7.28-1.el7.x86_64.rpm
  • rpm -ivh mysql-community-libs-compat-5.7.28-1.el7.x86_64.rpm
  • rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm
  • rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm

    删除 /etc/my.cnf文件中的datadir指向的目录下的所有内容

  • 删除 /var/lib/mysql目录下的所有内容

    • cd /var/lib/mysql
    • rm -rf ./*

      初始化数据库

  • mysqld --initialize --user=mysql

    查看临时生成的root用户密码

  • cat /var/log/mysqld.log

  • Bltw&2hktrM*

    启动Mysql服务

  • systemctl start mysqld

    登录mysql数据库

  • mysql -uroot -p

    修改root密码

  • set password = password("123456");

    修改mysql库下的user表中root用户允许任意ip连接

  • update mysql.user set host='%' where user='root';

  • flush privileges;

    Hive元数据配置到Mysql

    配置Metastore到Mysql

    创建 hive-site.xml文件

  • vi $HIVE_HOME/conf/hive-site.xml

  • 添加如下内容

    1. <?xml version="1.0"?>
    2. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
    3. <configuration>
    4. <!-- jdbc 连接的 URL -->
    5. <property>
    6. <name>javax.jdo.option.ConnectionURL</name>
    7. <value>jdbc:mysql://hadoop102:3306/metastore?useSSL=false</value>
    8. </property>
    9. <!-- jdbc 连接的 Driver-->
    10. <property>
    11. <name>javax.jdo.option.ConnectionDriverName</name>
    12. <value>com.mysql.jdbc.Driver</value>
    13. </property>
    14. <!-- jdbc 连接的 username-->
    15. <property>
    16. <name>javax.jdo.option.ConnectionUserName</name>
    17. <value>root</value>
    18. </property>
    19. <!-- jdbc 连接的 password -->
    20. <property>
    21. <name>javax.jdo.option.ConnectionPassword</name>
    22. <value>000000</value>
    23. </property>
    24. <!-- Hive 元数据存储版本的验证 -->
    25. <property>
    26. <name>hive.metastore.schema.verification</name>
    27. <value>false</value>
    28. </property>
    29. <!--元数据存储授权-->
    30. <property>
    31. <name>hive.metastore.event.db.notification.api.auth</name>
    32. <value>false</value>
    33. </property>
    34. <!-- Hive 默认在 HDFS 的工作目录 -->
    35. <property>
    36. <name>hive.metastore.warehouse.dir</name>
    37. <value>/user/hive/warehouse</value>
    38. </property>
    39. </configuration>

    登录mysql

  • mysql -uroot -p123456

    新建Hive元数据库

  • create database metastore;

    初始化Hive元数据库

  • [root@hadoop102 software]# schematool -initSchema -dbType mysql -verbose

    使用元数据服务的方式访问Hive

  • hive-site.xml文件中添加如下配置信息

    <!-- 指定存储元数据要连接的地址 --> 
    <property>
     <name>hive.metastore.uris</name>
     <value>thrift://hadoop102:9083</value>
    </property>
    
  • 启动metastore

    • hive --service metastore

      使用JDBC方式访问Hive

  • hive-site.xml文件中添加如下配置信息

    <!-- 指定 hiveserver2 连接的 host --> 
    <property>
    <name>hive.server2.thrift.bind.host</name>
    <value>hadoop102</value>
    </property>
    <!-- 指定 hiveserver2 连接的端口号 --> 
    <property>
    <name>hive.server2.thrift.port</name>
    <value>10000</value>
    </property>
    
  • 启动hiveserver2

    • [root@hadoop102 hive]# bin/hive --service hiveserver2
  • 启动beeline客户端

    • bin/hive -u jdbc:hive2://hadoop102:10000 -n atguigu

      编写hive服务启动脚本

  • 前台启动的方式导致需要打开多个shell窗口,可以使用如下方式后台启动

  • nohup 放在命令开头,表示不挂起
  • /dev/null 是linux文件系统中的一个文件,被称为黑洞,所有写入该文件的内容都会被自动丢弃
  • 2>&1 表示将错误重定向到标准输出上
  • & 放在命令结尾,表示后台运行
  • nohup hive --service metastore 2>&1 &

    编写hive脚本

  • vi $HIVE_HOME/bin/hiveservices.sh ```shell

    !/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`
- 后台Hive启动
   - `hiveservices.sh start`
<a name="TenEJ"></a>
## Hive常用交互命令
<a name="rLRbC"></a>
### 不进入hive窗口执行sql语句

- `bin/hive -e "select id from student;"`
<a name="eN7yq"></a>
### 执行脚本中sql语句

- 在 `/opt/module/hive`下创建`datas`目录,并在datas目录下创建`hivef.sql`文件
   - `touch hivef.sql`
- 在文件中写入sql语句
   - `select * from student;`
- 执行文件中的sql语句
   - `bin/hive -f /opt/module/hive/datas/hivef.sql`
- 执行文件中的sql语句并将结果写入文件中
   - `bin/hive -f /opt/module/hive/datas/hivef.sql > /opt/module/datas/hive_result.txt`
<a name="pS31f"></a>
## Hive其它命令操作

- 退出hive窗口
   - `quit;`
   - `exit;`
- 在`hive cli`命令窗口中查看hdfs文件系统
   - `dfs -ls /;`
- 查看hive中输入的所有历史命令
   - 进入到当前用户的根目录 `/root`
   - 查看`.hivehistory`文件
      - `cat .hivehistory`
<a name="kY5OY"></a>
## Hive常见属性配置
<a name="NKhww"></a>
### 修改配置文件位置

- 修改 `/opt/module/hive/conf/hive-log4j2.properties.template`为 `hive-log4j2.properties`
   - `[root@hadoop102 conf]# mv hive-log4j2.properties.template hive-log4j2.properties`
- 在 `hive-log4j2.properties`文件中修改log存放位置
   - `property.hive.log.dir = /opt/module/hive/logs`
<a name="iYjyy"></a>
### 打印当前库和表头

- 在 `hive-site.xml`中加入如下两个配置
```xml
<property>
  <name>hive.cli.print.header</name>
  <value>true</value>
</property>
<property>
  <name>hive.cli.print.current.db</name>
  <value>true</value>
</property>
  • image.png

    参数配置方式

  • 查看当前所有的配置信息

    • hive>set;

      参数配置的三种方式

  • 配置文件

    • 默认配置文件:hive-default.xml
    • 用户自定义配置文件:hive-site.xml
    • 注意:用户自定义配置会覆盖默认配置。另外,Hive也会读入Hadoop的配置,因为Hive是作为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置。配置文件的设定对本机启动的所有Hive进程都有效。
  • 命令行参数方式
    • 启动Hive时,可以在命令行添加-hiveconf param=value来设定参数
    • 仅对本次hive启动有效
  • 参数声明方式
    • 可以在HQL中使用ST关键字设定参数
      • set mapred.reduce.tasks=100;
    • 仅对本次hive启动有效
  1. 优先级:配置文件<命令行参数<参数声明

    Hive数据类型

    基本数据类型

    | Hive数据类型 | Java数据类型 | 长度 | 例子 | | —- | —- | —- | —- | | TINYINT | byte | 1byte有符号整数 | 20 | | SMALLINT | short | 2byte有符号整数 | 20 | | INT | int | 4byte有符号整数 | 20 | | BIGINT | long | 8byte有符号整数 | 20 | | BOOLEAN | boolean | 布尔类型,true或false | TRUE FALSE | | FLOAT | float | 单精度浮点数 | 3.14159 | | DOUBLE | double | 双精度浮点数 | 3.14159 | | STRING | string | 字符系列(单双引号) | “now is “ ‘now is’ | | TIMESTAMP | | 时间类型 | | | BINARY | | 字节数组 | |
  • 对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。

    集合数据类型

    | 数据类型 | 描述 | 语法示例 | | —- | —- | —- | | STRUCT | 和c语言中的struct类似,都可以通过”点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING,last STRING},那么第一个元素可以通过字段.first来引用 | struct()
    例如:
    struct | | MAP | MAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如:如果某个列的数据类型是MAP,其中键->值对是’first’->’John’ 和 ‘last’ ->’Doe’,那么可以通过字段名[‘last’]获取最后一个元素 | map()
    例如:
    map | | ARRAY | 数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,编号从零开始。i入,数组值为[‘John’,’Doe’],那么第2个元素可以通过数组名[1]进行引用 | Array()
    例如:array |

案例实操