Hive 保姆级入门教程

394 阅读12分钟

Apache Hive 从入门到放弃

Hive简介

  • Hive是什么

    • 基于Hadoop的数据仓库工具,可以用SQL查询Hive表
    • 实现了类似SQL的HiveQL,使得开发MapReduce应用更简单
    • 示例:SELECT * FROM table LIMIT 10;
  • Hive的优点

    • 易于使用,通过SQL开发大数据应用
    • 良好的扩展性,可处理PB级别的数据
    • 支持表join,group by, order by等复杂操作
    • 支持用户自定义函数,可扩展系统功能
  • Hive架构概览

    • 元数据存储在数据库如MySQL中
    • 解释器、编译器、优化器等组件负责编译查询
    • 使用MapReduce或Spark执行查询
    • 结果输出到HDFS或数据库

Hive安装

下载和安装Hive

  1. 在Linux服务器上安装wget工具: yum install -y wget

  2. 通过wget下载Hive安装包:

    wget https://dlcdn.apache.org/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
    
  3. 检查下载的文件完整性:

    md5sum apache-hive-3.1.3-bin.tar.gz
    # 对比显示的md5码与官网给定的md5码是否一致
    
  4. 创建安装目录,例如:/opt/hive

    mkdir /opt/hive
    
  5. 解压缩Hive压缩包到指定目录:

    tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /opt/hive
    
  6. 设置环境变量HIVE_HOME:

    export HIVE_HOME=/opt/hive/apache-hive-3.1.3-bin
    
  7. 将HIVE_HOME/bin添加到PATH:

    export PATH=$HIVE_HOME/bin:$PATH
    

配置Hive环境

  1. 配置hive-env.sh

进入Hive配置文件目录

cd $HIVE_HOME/conf

拷贝环境配置模板

cp hive-env.sh.template hive-env.sh

编辑hive-env.sh文件

vi hive-env.sh

在hive-env.sh中配置以下环境变量:

# Hive执行使用的Hadoop路径
HADOOP_HOME=/usr/local/hadoop 

# Hive运行使用Java的home
JAVA_HOME=/usr/java/jdk1.8.0_162

# Hive日志目录
HIVE_LOG_DIR=/tmp/hive/logs

# Hive元数据目录 
HIVE_METASTORE_WAREHOUSE=/tmp/hive/warehouse

保存退出后,重启Hive使得配置生效

  1. 配置hive-site.xml

编辑hive-site.xml:vi hive-site.xml

<configuration>

<!-- 设置MySQL JDBC连接URL -->
<property>
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>
</property>

<!-- MySQL 8.0 JDBC驱动类 -->
<property>
  <name>javax.jdo.option.ConnectionDriverName</name>
  <value>com.mysql.cj.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>
<property>
      <name>hive.metastore.warehouse.dir</name>
      <value>/user/hive/warehouse</value>
</property>

</configuration>

拷贝MySQL驱动到Hive

如果本地没有MySQL JDBC驱动,需要先下载该驱动再拷贝到Hive。那么具体的步骤为:

  1. 从MySQL官网下载对应版本的驱动连接器

    例如到 https://dev.mysql.com/downloads/connector/j/ 下载mysql-connector-java-8.0.11.tar.gz

  2. 解压驱动包获得jar文件

    tar zxvf mysql-connector-java-8.0.11.tar.gz
    
  3. 拷贝jar包到Hive的lib目录

    cp mysql-connector-java-8.0.11/mysql-connector-java-8.0.11.jar $HIVE_HOME/lib
    
  4. 验证并重启Hive

以上考虑了从MySQL官网下载驱动的情况,提前下载好驱动再拷贝到Hive。

如果本地已经具备了MySQL驱动,则可以直接拷贝,无需下载。

初始化MetaStore Schema

  1. 确认MySQL数据库已经创建好,并配置在hive-site.xml中

  2. 进入Hive的bin目录

    cd $HIVE_HOME/bin
    
  3. 执行Schema初始化

    schematool -initSchema -dbType mysql
    
  4. 如果成功会显示如下信息

    Metastore connection URL:  jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true
    Metastore Connection Driver :  com.mysql.cj.jdbc.Driver
    Metastore connection User:  root
    Starting metastore schema initialization to 3.1.0
    Initialization script hive-schema-3.1.0.mysql.sql
    
  5. 在MySQL数据库中可以查看新建的Hive元数据表,包括:

  • DBS - 记录数据库信息
  • TBLS - 记录表信息
  • COLUMNS_V2 - 记录列信息
  • PARTITIONS - 记录分区信息
  • SDS - 记录表/分区物理存储信息
  • SERDES - 记录序列化/反序列化类信息
  • TBL_PRIVS - 记录表权限信息
  • GLOBAL_PRIVS - 记录全局权限信息
  • ROLES - 记录角色信息
  • ROLE_MAP - 记录角色与用户关联信息
  • SEQUENCE_TABLE - 记录序列信息
  • INDEX_PARAMS - 记录索引信息
  • TYPE_FIELDS - 记录类型字段信息
  • TYPES - 记录类型信息
  • FUNCS - 记录函数信息
  • FUNC_RU - 记录函数与角色关联

配置完毕后测试启动

  1. 启动Hive命令行客户端

    hive
    
  2. 在hive命令行执行显示数据库列表查询

    show databases;
    
  3. 期望看到初始化的默认数据库

    OK
    default
    Time taken: 0.025 seconds, Fetched: 1 row(s)
    
  4. 创建一张测试表

    create table test(id int);
    
  5. 查看是否创建成功

    show tables;
    
  6. 期望看到test表

    OK
    test
    Time taken: 0.01 seconds, Fetched: 1 row(s)
    
  7. 退出hive命令行

    quit;
    

Hive服务部署

Hive的hiveserver2服务的作用是提供jdbc/odbc接口,为用户提供远程访问Hive数据的功能,例如用户期望在个人电脑中访问远程服务中的Hive数据,就需要用到Hiveserver2。

在远程访问Hive数据时,客户端并未直接访问Hadoop集群,而是由Hivesever2代理访问。由于Hadoop集群中的数据具备访问权限控制,所以此时需考虑一个问题:那就是访问Hadoop集群的用户身份是谁?是Hiveserver2的启动用户?还是客户端的登录用户?答案是都有可能,具体是谁,由Hiveserver2的hive.server2.enable.doAs参数决定,该参数的含义是是否启用Hiveserver2用户模拟的功能。若启用,则Hiveserver2会模拟成客户端的登录用户去访问Hadoop集群的数据,不启用,则Hivesever2会直接使用启动用户访问Hadoop集群数据。模拟用户的功能,默认是开启的。

生产环境推荐开启用户模拟功能,因为开启后才能保证各用户之间的权限隔离。

hiveserver2部署

  1. Hadoop端配置

hivesever2的模拟用户功能,依赖于Hadoop提供的proxy user(代理用户功能),只有Hadoop中的代理用户才能模拟其他用户的身份访问Hadoop集群。因此,需要将hiveserver2的启动用户设置为Hadoop的代理用户,配置方式如下:

修改配置文件core-site.xml,然后分发到各台服务器
cd $HADOOP_HOME/etc/hadoop
vim core-site.xml

增加配置如下:

<!--配置所有节点的hadoop用户都可作为代理用户-->
<property>
    <name>hadoop.proxyuser.hadoop.hosts</name>
    <value>*</value>
</property>

<!--配置hadoop用户能够代理的用户组为任意组-->
<property>
    <name>hadoop.proxyuser.hadoop.groups</name>
    <value>*</value>
</property>

<!--配置hadoop用户能够代理的用户为任意用户-->
<property>
    <name>hadoop.proxyuser.hadoop.users</name>
    <value>*</value>
</property>
  1. Hive端配置

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

# 打开文件
 vim 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>
  1. 测试

启动hiveserver2:bin/hive --service hiveserver2

使用命令行客户端beeline进行远程访问: bin/beeline -u jdbc:hive2://node01:10000 -n hadoop

看到如下界面

Connecting to jdbc:hive2://node01:10000
Connected to: Apache Hive (version 3.1.3)
Driver: Hive JDBC (version 3.1.3)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 3.1.3 by Apache Hive
0: jdbc:hive2://node01:10000>

metastore服务

Hive的metastore服务的作用是为Hive CLI或者Hiveserver2提供元数据访问接口。

  1. metastore运行模式

metastore有两种运行模式,分别为嵌入式模式和独立服务模式。生产环境中,不推荐使用嵌入式模式。因为其存在以下两个问题:

  • 嵌入式模式下,每个Hive CLI都需要直接连接元数据库,当Hive CLI较多时,数据库压力会比较大。
  • 每个客户端都需要用户元数据库的读写权限,元数据库的安全得不到很好的保证。
  1. metastore部署

嵌入式模式:嵌入式模式下,只需保证Hiveserver2和每个Hive CLI的配置文件hive-site.xml中包含连接元数据库所需要的以下参数即可:

 <!-- jdbc连接的URL -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://hadonode01op102:3306/metastore?useSSL=false</value>
    </property>
    
    <!-- jdbc连接的Driver,需要区分MySQL版本-->
    <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>root</value>
    </property>

独立服务模式:需做以下配置,首先,保证metastore服务的配置文件hive-site.xml中包含连接元数据库所需的以下参数:

<!-- jdbc连接的URL -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://node01:3306/metastore?useSSL=false</value>
    </property>
    
    <!-- jdbc连接的Driver,需要区分MySQL版本-->
    <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>root</value>
    </property>

其次,保证Hiveserver2和每个Hive CLI的配置文件hive-site.xml中包含访问metastore服务所需的以下参数:

<!-- 指定metastore服务的地址 -->
<property>
 <name>hive.metastore.uris</name>
 <value>thrift://node01:9083</value>
</property>

注意:主机名需要改为metastore服务所在节点,端口号无需修改,metastore服务的默认端口就是9083。

  1. 测试

此时启动Hive CLI,执行shou databases语句,会出现一下错误提示信息:

hive (default)> show databases;
FAILED: HiveException java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

这是因为我们在Hive CLI的配置文件中配置了hive.metastore.uris参数,此时Hive CLI会去请求我们执行的metastore服务地址,所以必须启动metastore服务才能正常使用。

metastore服务的启动命令如下:hive --service metastore

注意:启动后该窗口不能再操作,需打开一个新的Xshell窗口来对Hive操作。

重新启动 Hive CLI(bin/hive),并执行shou databases语句,就能正常访问了。

Hive服务启动脚本

  1. 后台启动方式

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

  • nohup:放在命令开头,表示不挂起,也就是关闭终端进程也继续保持运行状态
  • /dev/null:是Linux文件系统中的一个文件,被称为黑洞,所有写入该文件的内容都会被自动丢弃
  • 2>&1:表示将错误重定向到标准输出上
  • &:放在命令结尾,表示后台运行

一般会组合使用:nohup [xxx命令操作]> file 2>&1 &,表示将xxx命令运行的结果输出到file中,并保持命令启动的进程在后台运行。

nohup hive --service metastore 2>&1 &
nohup hive --service hiveserver2 2>&1 &
  1. 为了方便使用,可以直接编写脚本来管理服务的启动和关闭
# 打开文件
vim $HIVE_HOME/bin/hiveservices.sh
# 添加内容
#!/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 hive --service 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

Hive数据类型

  1. 原始数据类型
  • TINYINT: 1字节整型,取值范围:-128 ~ 127
  • SMALLINT: 2字节整型,取值范围:-32768 ~ 32767
  • INT: 4字节整型,取值范围:-2147483648 ~ 2147483647
  • BIGINT: 8字节整型,取值范围:-9223372036854775808 ~ 9223372036854775807
  • FLOAT: 单精度浮点数,4字节
  • DOUBLE: 双精度浮点数,8字节
  • DECIMAL: 准确的小数值,参数指定精度和范围
  • STRING: 字符系列,可指定长度
  • VARCHAR: 变长字符串,最大长度65535
  • CHAR: 定长字符串,长度1~255
  • BOOLEAN: true/false
  • DATE: 日期格式,yyyy-MM-dd
  • TIMESTAMP: 时间戳格式,yyyy-MM-dd HH:mm:ss
  1. 复杂数据类型
  • ARRAY: 索引从0开始的数组,元素类型可以不同

    如 ARRAY, ARRAY

  • MAP: key-value映射表格式

    如 MAP<STRING, INT>

  • STRUCT: 字段集合,类型可以不同

    如 STRUCT<name:STRING, age:INT>

  1. 数据格式
  • ORC: 列式存储数据格式,压缩效率高
  • Parquet: 面向分析查询的列式存储格式
  • Avro: 序列化数据交换格式
  • JSON: 一种文本序列化格式

Hive操作

创建/删除/修改数据库

  • 创建数据库

    CREATE DATABASE mydb;
    
  • 查看数据库

    SHOW DATABASES;
    
  • 删除数据库

    DROP DATABASE mydb;
    
  • 修改数据库

    ALTER DATABASE mydb SET DBPROPERTIES('comment' = 'db comment')
    

创建/删除/修改表

  • 创建表

    CREATE TABLE mytab (col1 STRING, col2 INTROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
    STORED AS TEXTFILE;
    
  • 查看表

    SHOW TABLES;
    DESCRIBE mytab;
    
  • 删除表

    DROP TABLE mytab;
    
  • 修改表

    ALTER TABLE mytab ADD COLUMNS (col3 INT);
    ALTER TABLE mytab CHANGE col1 col1_new INT

载入数据

  • 加载本地文件到表

    LOAD DATA LOCAL INPATH '/tmp/data.txt' OVERWRITE INTO TABLE mytab;
    
  • 通过查询插入数据

    INSERT INTO TABLE mytab SELECT * FROM oldtab;
    
  • 创建表时载入数据

    CREATE TABLE newtab AS SELECT * FROM mytab;
    

查询数据

  • 全表查询

    SELECT * FROM mytab;
    
  • 条件过滤

    SELECT * FROM mytab WHERE col1='value';
    
  • 分组和聚合

    SELECT COUNT(*FROM mytab GROUP BY col2;
    
  • 排序和限制

    SELECT * FROM mytab ORDER BY col2 DESC LIMIT 10;
    

修改表结构

  • 添加列

    ALTER TABLE mytab ADD COLUMNS (newcol STRING);
    
  • 更改列

    ALTER TABLE mytab CHANGE COLUMN col1 newcol INT;
    
  • 替换列

    ALTER TABLE mytab REPLACE COLUMNS (col1 STRING, col2 INT);
    

分区表操作

  • 创建分区表

    CREATE TABLE mytab (col1 STRING, col2 INT) 
    PARTITIONED BY (partcol STRING)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
    
  • 加载数据到分区

    LOAD DATA LOCAL INPATH '/tmp/data1.txt' INTO TABLE mytab PARTITION (partcol='part1'); 
    
    LOAD DATA LOCAL INPATH '/tmp/data2.txt' INTO TABLE mytab PARTITION (partcol='part2');
    
  • 查询分区数据

    SELECT * FROM mytab WHERE partcol='part1';
    
  • 增加分区

    ALTER TABLE mytab ADD PARTITION (partcol='part3') LOCATION '/path/to/part3';
    
  • 删除分区

    ALTER TABLE mytab DROP PARTITION (partcol='part1');
    

桶表操作

  • 创建桶表

    CREATE TABLE mytab (col1 STRING, col2 INT)
    CLUSTERED BY (col2) INTO 4 BUCKETS
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  • 加载数据到桶表

    LOAD DATA LOCAL INPATH '/tmp/data.txt' INTO TABLE mytab;
    
  • 抽样查询

    SELECT * FROM mytab TABLESAMPLE(BUCKET 1 OUT OF 4 ON col2); 
    
  • 插入数据到指定桶

    INSERT INTO TABLE mytab CLUSTER BY (col2) 
    SELECT key, value FROM src LIMIT 100;
    
  • 删除指定桶数据

    ALTER TABLE mytab DROP IF EXISTS PARTITION (col2=5); 
    

HiveQL

Data Definition Language (DDL)

  • 创建数据库

    CREATE DATABASE mydb;
    
  • 创建表

    CREATE TABLE mytab (col1 STRING, col2 INT)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
    
  • 创建视图

    CREATE VIEW myview AS SELECT col1, col2 FROM mytab WHERE col2 > 1;
    
  • 删除数据库/表/视图

    DROP DATABASE mydb;
    DROP TABLE mytab;
    DROP VIEW myview;
    

Data Manipulation Language (DML)

  • 载入数据

    LOAD DATA LOCAL INPATH '/tmp/data.txt' OVERWRITE INTO TABLE mytab;
    
  • 插入数据

    INSERT INTO TABLE mytab VALUES ('val1'2);
    INSERT INTO TABLE mytab (col1, col2) VALUES ('val2'3);
    
  • 更新数据

    UPDATE mytab SET col1='newval' WHERE col2=2;
    
  • 删除数据

    DELETE FROM mytab WHERE col2=3;
    

查询语言

  • 基础查询

    SELECT * FROM mytab;
    SELECT col1, col2 FROM mytab;
    
  • 条件过滤

    SELECT * FROM mytab WHERE col1='val';
    
  • 排序和限制

    SELECT * FROM mytab ORDER BY col2 DESC LIMIT 5;
    
  • 聚合查询

    SELECT COUNT(*FROM mytab;
    SELECT MAX(col2) FROM mytab;
    
  • 分组

    SELECT col1, COUNT(*FROM mytab GROUP BY col1; 
    
  • JOIN

    SELECT * FROM tab1 JOIN tab2 ON tab1.id = tab2.id;
    

Hive架构

  1. 元数据存储(Metastore)
  • 默认内置的Apache Derby数据库
  • 也支持MySQL、Postgres等外部数据库
  • 存储数据库、表、分区、列的数据类型信息
  • metastore服务通过Thrift提供元数据访问接口
  1. Driver(HiveDriver)
  • 接收来自CLI/JDBC/ODBC的查询请求
  • 进行语法解析生成抽象语法树AST
  • 生成逻辑执行计划
  • 优化逻辑计划,生成最优物理计划
  • 生成MapReduce、Spark或Tez任务
  • 向执行引擎提交作业执行
  1. 编译器(Compiler)
  • 对AST进行类型检查、语义分析
  • 生成逻辑执行计划
  • 针对DDL语句生成元数据操作
  1. 优化器(Optimizer)
  • 对逻辑计划进行优化,产出多种物理计划
  • 选择代价最低的物理计划
  • 物理优化包括join优化、groupby优化等
  1. 执行器(Executor)
  • 接收物理计划,生成MapReduce/Spark/Tez任务
  • 提交给YARN集群执行作业
  • 控制作业的生命周期
  • 通过列式存储格式实现向量化查询
  1. 客户端
  • CLI(hive shell)
  • JDBC/ODBC - 通过JDBC连接HiveServer2
  • Web UI - 基于网页的Hive查询接口
  • Thrift/JDBC - 元数据访问接口

Hive优化

Join优化

  • 将大表设置为桶表,加快JOIN速度

    SET hive.optimize.bucketmapjoin = true
    SET hive.optimize.bucketmapjoin.sortedmerge = true;
    
  • 使用Map Join,避免reduce端数据shuffle

    SET hive.auto.convert.join = true;
    

数据倾斜

  • 使用抽样和分桶,提前识别和缓解数据倾斜

    CLUSTERED BY(col) INTO NUM BUCKETS; 
    TABLESAMPLE(BUCKET 1 OUT OF NUM)
    
  • 调整map数为表分桶数的整数倍

    SET mapreduce.job.maps=15;
    

小文件合并

  • 使用CombineHiveInputFormat完成合并

    SET mapreduce.input.fileinputformat.input.dir.recursive = true;
    

设置任务并行度

  • 设置map数,增加并行度

    SET mapreduce.job.maps=20;
    
  • 设置reduce数,增大并行

    SET mapreduce.job.reduces=10;
    

压缩

  • 对中间输出进行压缩

    SET hive.exec.compress.intermediate=true
    
  • 对最终输出结果进行压缩

    SET hive.exec.compress.output=true;
    

    好的,我用Markdown格式,尽量详细地概述Hive的各种优化策略,并给出参数设置和使用案例:

本地模式

利用本地多核心执行任务,跳过YARN资源调度

设置参数:
hive.exec.mode.local.auto=true

案例:

SET hive.exec.mode.local.auto=true;

SELECT * FROM small_table LIMIT 10

上述查询会在本地多核心CPU上并行执行

分桶&抽样

利用分桶和抽样解决数据倾斜问题

设置参数:
CLUSTERED BY(col) INTO BUCKETS
TABLESAMPLE(BUCKET x OUT OF y)

案例:

CREATE TABLE page_views 
CLUSTERED BY(pageID) INTO 128 BUCKETS;

SELECT * FROM page_views TABLESAMPLE(BUCKET 5 OUT OF 128);

Hive on Spark

Hive on Spark利用Spark作为Hive查询的执行引擎,以实现更高的查询性能

运行原理

  1. Hive的Driver接收并编译SQL查询
  2. 产生Spark作业对应的执行计划
  3. 在Spark集群上并行执行查询计划
  4. 返回结果给Hive Driver

配置方法

在hive-site.xml中设置参数:

hive.execution.engine=spark

使用案例

SET hive.execution.engine=spark;

SELECT * FROM tbl;

上述查询会使用Spark作为执行引擎,实现快速查询

优点

  • 利用Spark的执行速度优势
  • 低延迟,实时查询
  • 处理流式数据
  • 与机器学习集成

Hive on Spark让Hive可以享受Spark带来的性能优势,构建低延迟和实时的大数据分析平台。

Hive 事务

Hive从0.13版本开始支持基于MVCC的事务功能

ACID特性

Hive表开启事务后,可以支持原子性、一致性、隔离性的事务:

  • 支持插入/更新/删除行的事务改变
  • 事务隔离,读取可重复读版本的数据视图
  • 满足ACID特性,保证事务一致性

事务操作

-- 开始事务
START TRANSACTION;

-- 查询
SELECT * FROM table WHERE id=1 FOR UPDATE-- 数据修改  
UPDATE table SET col='new_value' WHERE id=1;

-- 提交事务
COMMIT;

需要先设置表为事务表:ALTER TABLE table SET TBLPROPERTIES('transactional'='true');

使用案例

ALTER TABLE table SET TBLPROPERTIES('transactional'='true');

START TRANSACTION;

UPDATE table SET col='v1' WHERE id=1;
UPDATE table SET col='v2' WHERE id=2;

COMMIT;

窗口函数

RANK()

按指定字段排序后进行排名,排名相同会重复

RANK() OVER (PARTITION BY dept ORDER BY salary DESCAS rank

案例:按部门分区,按薪水降序排名,相同薪水会重复排名

DENSE_RANK()

按指定字段排序后进行排名,排名相同会跳过编号

DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESCAS dense_rank 

案例:按部门和薪水排名,相同薪水跳过排名编号

ROW_NUMBER()

按指定字段排序,为每行生成一个连续递增的编号

ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESCAS row_num

案例:按部门和薪水给每行生成一个编号,按降序排序

LEAD()/LAG()

获取当前行在窗口分区中往后/前指定偏移量行的字段值

LEAD(salary, 1OVER (PARTITION BY dept ORDER BY salary DESCLAG(salary, 1OVER (PARTITION BY dept ORDER BY salary DESC)

案例:获取当前行后面/前面一行的salary值

FIRST_VALUE()/LAST_VALUE()

获取窗口分区中排序后第一行/最后一行指定字段的值

FIRST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary DESC)
LAST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary DESC

案例:获取部门薪水排名第一/最后的salary

NTILE()

将窗口分区中的行分发到指定的组中,各组有编号

NTILE(2OVER (PARTITION BY dept ORDER BY salary DESC)

案例:按薪水排名后,将部门内员工分为2组

CUME_DIST()

计算当前行在窗口分区中的累积分布值(百分位数)

CUME_DIST() OVER (PARTITION BY dept ORDER BY salary DESC)

案例:计算当前薪水在部门中的百分位数排名

PERCENT_RANK()

计算当前行在窗口分区中的百分比排名

PERCENT_RANK() OVER (PARTITION BY dept ORDER BY salary DESC)  

案例:计算当前薪水在部门的百分比排名