Hive - 安装与使用

目录

一、基本概念

[1、什么是 Hive](#1、什么是 Hive)

2、优缺点

3、架构原理

[4、Hive 和数据库比较](#4、Hive 和数据库比较)

[二、Hive 安装](#二、Hive 安装)

1、安装地址

2、安装部署

[(1)安装 Hive](#(1)安装 Hive)

(2)使用Hive

3、Hive元数据配置到MySQL

(1)拷贝驱动

(2)配置Metastore到MySQL

(3)再次启动Hive

4、使用元数据服务访问Hive

(1)添加配置信息

(2)启动metastore

[(3)启动 hive](#(3)启动 hive)

​编辑

5、使用JDBC方式访问Hive

(1)添加配置信息

​编辑

(2)启动metastore元数据

(3)启动hiveserver2

​编辑

(4)启动beeline客户端

(5)编写hive服务启动脚本

6、常用命令

(1)"-e"

(2)"-f"

(3)退出hive窗口

(4)查看hdfs文件系统

(5)历史命令

7、常见属性配置

(1)日志信息配置

(2)打印当前库和表头

(3)修改配置参数

三、数据类型

1、基本数据类型

2、集合数据类型

(1)数据类型

(2)案例

3、类型转化

四、DDL操作

1、创建数据库

(1)基本语法

(2)操作

2、查询数据库

(1)显示数据库

(2)过滤显示

(3)显示数据库信息

(4)显示详细信息

3、切换数据库

4、修改数据库

5、删除数据库

(1)删除空数据库

(2)判断后删除

(3)强制删除

6、创建表

(1)基本语法

(2)管理表(内部表)

​编辑

(3)外部表

(4)内与外部表的互相转换

7、修改表

(1)修改表名

(2)操作列

1)新增列

2)更新列

3)替换列

4)删除列

(3)删除表

五、DML数据操作

1、数据导入

(1)加载数据Load

1)语法

2)加载本地文件到hive

3)加载HDFS文件到hive中

4)覆盖表中数据

(2)插入数据Insert

1)基本插入

2)单表查询结果插入

3)查询结果插入多表

[(3)查询中创建表As Select](#(3)查询中创建表As Select)

2、数据导出

[(1)Insert 导出](#(1)Insert 导出)

(2)Hadoop导出本地

[(3)Hive Shell命令导出](#(3)Hive Shell命令导出)

3、清除表中数据

六、查询

1、基本查询

(1)全表查询

(2)指定列查询

(3)列别名

(4)算术运算符

(5)常用函数

1)总行数count()

2)最大值max()

3)最小值min()

4)总和sum()

5)平均值avg()

[(6)Limit 语句](#(6)Limit 语句)

(7)Where语句

(8)比较运算符

[(9)Like 和 RLike](#(9)Like 和 RLike)

(10)逻辑运算符

2、分组

[(1)Group By](#(1)Group By)

​编辑

(2)Having

[3、Join 语句](#3、Join 语句)

(1)表的别名

(2)内连接

(3)左外连接

(4)右外连接

(5)满外连接

(6)左排除连接

(7)右排除连接

(8)外部排除连接

(9)多表连接查询

(10)笛卡尔积

4、排序

[(1)全局排序(Order By)](#(1)全局排序(Order By))

​编辑

[(2)内部排序(Sort By)](#(2)内部排序(Sort By))

[(3)分区(Distribute By)](#(3)分区(Distribute By))

[(4)Cluster By](#(4)Cluster By)

七、分区表和分桶表

1、分区表

(1)基本操作

1)创建分区表

2)查询数据

3)增加分区

4)删除分区

5)查看分区

6)查看分区表结构

(2)二级分区

1)创建二级分区表

2)加载数据

3)分区表和数据产生关联

(3)动态分区调整

1)开启动态分区参数设置

2)案例

2、分桶表

(1)创建分桶表

(2)注意的事项

(3)insert导入数据

3、抽样查询


一、基本概念

1、什么是 Hive

(1)hive 简介

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

(2) Hive 本质:将 HQL 转化成 MapReduce 程序

(1)Hive 处理的数据存储在 HDFS

(2)Hive 分析数据底层的实现是 MapReduce

(3)执行程序运行在 Yarn 上

2、优缺点

(1)优点

1)操作接口采用类 SQL 语法,提供快速开发的能力(简单、容易上手)。

2)避免了去写 MapReduce,减少开发人员的学习成本。

3)Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合。

4)Hive优势在于处理大数据,对处理小数据没有优势,因为 Hive的执行延迟比较高。

5)Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。

(2)缺点

1)Hive 的 HQL 表达能力有限

(1)迭代式算法无法表达

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

2)Hive 的效率比较低

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

(2)Hive 调优比较困难,粒度较粗

3、架构原理

(1)用户接口:Client

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

(2)元数据:Metastore

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

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

(3)Hadoop

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

(4)驱动器:Driver

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

2)编译器(Physical Plan):将 AST 编译生成逻辑执行计划。

3)优化器(Query Optimizer):对逻辑执行计划进行优化。

4)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于 Hive 来说,就是 MR/Spark。

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

4、Hive****和数据库比较

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

(1)查询语言

由于 SQL 被广泛的应用在数据仓库中,因此,专门针对 Hive 的特性设计了类 SQL 的查

询语言 HQL。熟悉 SQL 开发的开发者可以很方便的使用 Hive 进行开发。

(2)数据更新

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

(3)执行延迟

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

(4)数据规模

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

二、Hive****安装

1、安装地址

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

2、安装部署

(1)安装 Hive

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


2)解压 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/

3)修改 apache-hive-3.1.2-bin.tar.gz 的名称为 hive

cd /opt/module/

mv apache-hive-3.1.2-bin/ hive

4)修改 /etc/profile,添加环境变量

sudo vim /etc/profile

添加内容

#HIVE_HOME

export HIVE_HOME=/opt/module/hive

export PATH=PATH:HIVE_HOME/bin

5)解决日志 Jar 包冲突

mv HIVE_HOME/lib/log4j-slf4j-impl-2.10.0.jar HIVE_HOME/lib/log4j-slf4j-impl-2.10.0.bak

6)初始化元数据库

bin/schematool -dbType derby -initSchema

(2)使用Hive

0)启动Hadoop

在启动Hive之前需要先启动Hadoop,因为Hive是依赖于Hadoop的。

1)启动Hive

bin/hive

2)使用Hive

显示数据库

show database;

显示表

show tables;

创建表

create table test(id int);

插入数据

insert into test values(1);

查询数据

select * from test;

3)异常说明
如果开启一个新的窗口启动Hive,查看在 /tmp/hdhk 目录下监控 hive.log 文件

Caused by: ERROR XSDB6: Another instance of Derby may have already booted the database /opt/module/hive/metastore_db. at org.apache.derby.iapi.error.StandardException.newException(Unknown

Source) at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.privGetJBMSLockO

nDB(Unknown Source) at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.run(Unknown Source)

原因在于 Hive 默认使用的元数据库为 derby,开启 Hive 之后就会占用元数据库,且不与其他客户端共享数据,所以我们需要将 Hive 的元数据地址改为 MySQL。意思就是只能有一个客户端使用Hive。

3、Hive元数据配置到MySQL

(1)拷贝驱动

将MySQL的JDBC驱动拷贝到Hive的lib目录下

cp mysql-connector-java-8.0.13.jar /opt/module/hive/lib/

(2)配置Metastore到MySQL

1)在$HIVE_HOME/conf目录下新建hive-site.xml文件

cd $HIVE_HOME/conf

vim hive-site.xml

添加如下内容

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://192.168.10.139:3306/metastore?useUnicode=true&amp;uss
eSSL=true&amp;serverTimezone=GMT%2B8</value> 
    </property> 
 
    <!-- jdbc连接的Driver--> 
    <property> 
        <name>javax.jdo.option.ConnectionDriverName</name> 
        <value>com.mysql.cj.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> 
 
    <!-- 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> 

2)新建Hive元数据库

在可视化工具上连接MySQL,创建metastore数据库

3)初始化Hive元数据库

schematool -initSchema -dbType mysql verbose

(3)再次启动Hive

1)启动Hive

hdhk@hd01 hive\]$ bin/hive

2)使用Hive

hive> show databases;

hive> show tables;

hive> create table test (id int);

hive> insert into test values(1);

hive> select * from test;

4、使用元数据服务访问Hive

(1)添加配置信息

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

<!-- 指定存储元数据要连接的地址 -->

<property>

<name>hive.metastore.uris</name>

<value>thrift://hd01:9083</value>

</property>

(2)启动metastore

hive --service metastore

注意: 启动后窗口不能再操作,需打开一个新的shell窗口做别的操作

(3)启动 hive

bin/hive

5、使用JDBC方式访问Hive

(1)添加配置信息

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

<!-- 指定hiveserver2连接的host -->

<property>

<name>hive.server2.thrift.bind.host</name>

<value>hd01</value>

</property>

<!-- 指定hiveserver2连接的端口号 -->

<property>

<name>hive.server2.thrift.port</name>

<value>10000</value>

</property>

(2)启动metastore元数据

hive --service metastore

注意: 启动后窗口不能再操作,需打开一个新的shell窗口做别的操作

(3)启动hiveserver2

bin/hive --service hiveserver2

窗体不要关闭,开启一个新的窗体

日志出现错误,不用管多等待一会

(4)启动beeline客户端

(需要多等待一会)

bin/beeline -u jdbc:hive2://hd01:10000 -n hdhk

如果出现如下错误:

修改Hadoop的配置文件core-site.xml文件

增加如下配置:hdhk改为自己的名字,修改后重启Hadoop和Hive

<property>

<name>hadoop.proxyuser.hdhk.hosts</name>

<value>*</value>

</property>

<property>

<name>hadoop.proxyuser.hdhk.groups</name>

<value>*</value>

</property>

(5)编写hive服务启动脚本

前台启动的方式导致需要打开多个shell窗口,这些窗口不能关闭,可以使用如下脚本:

基本参数了解:

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

组合使用:

nohup [xxx命令操作] > file 2>&1 &

表示:表示将xxx命令运行的结 果输出到file中,并保持命令启动的进程在后台运行

1)编写脚本命令

在hive/bin目录下面创建hiveservices.sh文件

bash 复制代码
#!/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 5 
    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 

2)添加执行权限

chmod +x $HIVE_HOME/bin/hiveservices.sh

3)启动Hive后台服务

hiveservices.sh start

6、常用命令

bin/hive -help

(1)"-e"

"-e"不进入hive的交互窗口执行sql语句

bin/hive -e "select id from test;"

(2)"-f"

"-f"执行脚本中sql语句

在/opt/module/hive/下创建 datas 目录并在datas目录下创建hivef.sql文件

hivef.sql 内容如下

select *from test;

执行文件中的sql语句

bin/hive -f /opt/module/hive/datas/hivef.sql

执行文件中的sql语句并将结果写入文件中

bin/hive -f /opt/module/hive/datas/hivef.sql > /opt/module/hive/datas/hive_result.txt

(3)退出hive窗口

>exit;

>quit;

(4)查看hdfs文件系统

在hive cli 命令窗口中如何查看hdfs文件系统

>dfs -ls /;

(5)历史命令

查看在hive中输入的所有历史命令

进入到当前用户的根目录 /home/用户名

查看 .hivehistory 文件

7、常见属性配置

(1)日志信息配置

Hive 的log默认存放在/tmp/当前用户名/hive.log 目录下,

例如:修改hive的log存放日志到/opt/module/hive/logs

1、修改conf/hive-log4j2.properties.template 文件名称为 hive-log4j2.properties

2、在hive-log4j2.properties 文件中修改 log 存放位置

hive.log.dir=/opt/module/hive/logs

(2)打印当前库和表头

默认不显示库名,在查询数据时也不显示表头

修改hive-site.xml文件 添加如下配置

<property>

<name>hive.cli.print.header</name>

<value>true</value>

</property>

<property>

<name>hive.cli.print.current.db</name>

<value>true</value>

</property>

再次查看

(3)修改配置参数

1)配置文件方式

默认配置文件:hive-default.xml

用户自定义配置文件:hive-site.xml

注意:用户自定义配置会覆盖默认配置。另外,Hive也会读入Hadoop的配置,因为Hive 是作为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置。配置文件的设定对本机启动的所有Hive进程都有效。

2)命令行参数方式

启动Hive时,可以在命令行添加 -hiveconf param=value 来设定参数。

例如: bin/hive -hiveconf mapred.reduce.tasks=10;

注意:仅对本次hive启动有效

查看参数设置: hive (default)> set mapred.reduce.tasks;

3)参数声明方式

可以在HQL中使用SET关键字设定参数

例如: hive (default)> set mapred.reduce.tasks=100;

注意:仅对本次hive启动有效。

查看参数设置 hive (default)> set mapred.reduce.tasks;

上述三种设定方式的优先级依次递增。即配置文件 < 命令行参数 < 参数声明

注意某些系统级的参数,例如log4j相关的设定,必须用前两种方式设定,因为那些参数的读取在会话建立以前已经完成了。

三、数据类型

1、基本数据类型

|------------|-----------|----------------------------|-------------------|
| Hive 数据类型 | Java 数据类型 | 长度 | 例子 |
| TINYINT | byte | 1byte 有符号整数 | 20 |
| SMALINT | short | 2byte 有符号整数 | 20 |
| INT | int | 4byte 有符号整数 | 20 |
| BIGINT | long | 8byte 有符号整数 | 20 |
| BOOLEAN | boolean | 布尔类型,true 或者false | TRUE/FALSE |
| FLOAT | float | 单精度浮点数 | 3.1315 |
| DOUBLE | double | 双精度浮点数 | 3.1415 |
| STRING | string | 字符系列。可以指定字符集。可以使用单引号或者双 引号 | 'hello' / "hello" |
| TIMESTAMP | | 时间类型 | |
| BINARY | | 字节数组 | |

对于Hive的String 类型相当于数据库的 varchar 类型,该类型是一个可变的字符串,不 过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。

2、集合数据类型

(1)数据类型

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

(2)案例

用JSON格式来表示其数据结构。在Hive下访问的格式为

{

"name": "李四",

"friends": ["小明" , "小红"], //列表Array,

"children": { //键值Map,

"li-1": 18 ,

"li-2": 19

},

"address": { //结构Struct,

"street": "南京",

"city": "江苏"

}

}

1)创建要导入的数据文件

李四,小明_小红,li-1:18_li-2:19,南京_江苏

zhangsan,xiaoming_xiaohong,zhang-1:18_zhang-2:19,wuxi_jiangsu

注意:MAP,STRUCT和ARRAY里的元素间关系都可以用同一个字符表示,这里用"_"。

2)创建对应的表

创建test2表

create table test(

name string,

friends array<string>,

children map<string, int>,

address struct<street:string, city:string>

)

row format delimited

fields terminated by ','

collection items terminated by '_'

map keys terminated by ':'

lines terminated by '\n';

字段说明:

|-----------------------------------------------|---------------------------------|
| row format delimited fields terminated by ',' | 列分隔符 |
| collection items terminated by '_' | MAP STRUCT 和 ARRAY 的分隔符(数据分割符号) |
| map keys terminated by ':' | MAP 中的key与value的分隔符 |
| lines terminated by '\n' | 行分隔符 |

3)导入数据

hadoop fs -put text.txt /user/hive/warehouse/test2

4)访问三种集合列里的数据

数组: 字段名[角标]

map:字段名['key名']

struct:字段名.属性名

1.查询所有数据

2.查询 friends数组字段

3.查询 children map类型字段

4.查询 address struct类型字段

3、类型转化

Hive 的原子数据类型是可以进行隐式转换的,类似于Java 的类型转换,例如某表达式 使用INT类型,TINYINT会自动转换为INT类型,但是Hive不会进行反向转化,例如,某表 达式使用TINYINT类型,INT不会自动转换为TINYINT类型,它会返回错误,除非使用CAST 操作。

(1)隐式类型转换规则如下

  • 任何整数类型都可以隐式地转换为一个范围更广的类型,如TINYINT可以转换成 INT,INT 可以转换成BIGINT。
  • 所有整数类型、FLOAT和STRING类型都可以隐式地转换成DOUBLE。
  • TINYINT、SMALLINT、INT 都可以转换为FLOAT。
  • BOOLEAN类型不可以转换为任何其它的类型。

(2)可以使用CAST操作显示进行数据类型转换。

例如 CAST('1' AS INT) 将把字符串'1' 转换成整数1;如果强制类型转换失败,如执行 CAST('X' AS INT),表达式返回空值 NULL。

四、DDL操作

1、创建数据库

(1)基本语法

CREATE DATABASE [IF NOT EXISTS] database_name

COMMENT database_comment

LOCATION hdfs_path

WITH DBPROPERTIES (property_name=property_value, ...)\];

说明:

  • IF NOT EXISTS: 数据库不存在则创建
  • COMMENT:数据库描述
  • LOCATION:数据库在hdfs上的存储地址,数据库在HDFS上的默认存储路径是 /user/hive/warehouse/*.db
  • WITH DBPROPERTIES:其他参数信息,如创建时间等

(2)操作

create database if not exists hive_test comment '测试' location 'hive_test'

create database if not exists hive_test2 comment '测试2' location '/hive_test2'

2、查询数据库

(1)显示数据库

show databases;

(2)过滤显示

show databases like '库名*';

(3)显示数据库信息

desc database 库名;

(4)显示详细信息

desc database extended 库名;

3、切换数据库

use 库名;

4、修改数据库

修改数据库的DBPROPERTIES 设置键-值对属性值, 来描述这个数据库的属性信息。

alter database 库名 set dbproperties('键'='值');

5、删除数据库

(1)删除空数据库

drop database 库名;

(2)判断后删除

drop database if exists 库名;

(3)强制删除

当数据库存在表时需要强制删除

drop database 库名 cascade;

6、创建表

(1)基本语法

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

(col_name data_type \[COMMENT col_comment\], ...)

COMMENT table_comment

PARTITIONED BY (col_name data_type \[COMMENT col_comment\], ...)

CLUSTERED BY (col_name, col_name, ...) \[SORTED BY (col_name \[ASC\|DESC\], ...)\] INTO num_buckets BUCKETS

ROW FORMAT row_format

STORED AS file_format

LOCATION hdfs_path

TBLPROPERTIES (property_name=property_value, ...)

AS select_statement

参数说明:

1)CREATE TABLE: 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;可以用 IF NOT EXISTS 选项来忽略这个异常。

2)EXTERNAL: 关键字,创建一个外部表,在建表的同时可以指定一个指向实际数据的路径(LOCATION),在删除表的时候,内部表的元数据和数据会被一起删除,而外 部表只删除元数据,不删除数据。

3)**COMMENT:**为表和列添加注释。

4)**PARTITIONED BY:**创建分区表

5)**CLUSTERED BY:**创建分桶表

6)SORTED BY: 不常用,对桶中的一个或多个列另外排序

7)ROW FORMAT: ROW FORMAT DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)] 在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者ROW FORMAT DELIMITED,将会使用自带的SerDe。在建表的时候,还需要为表指定列,在指定表的列的同时也会指定自定义的SerDe,Hive通过SerDe确定表 的具体的列的数据。 SerDe 是 Serialize/Deserilize 的简称, hive 使用 Serde 进行行对象的序列与反序列化。

8)**STORED AS:**指定存储文件类型 常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列 式存储格式文件) 如果文件数据是纯文本,可以使用STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。

9)**LOCATION :**指定表在HDFS上的存储位置。

10)**AS:**后跟查询语句,根据查询结果创建表。

11)**LIKE:**允许用户复制现有的表结构,但是不复制数据。

(2)管理表(内部表)

默认创建的表都是所谓的管理表(内部表)。因为这种表,Hive会(或多或 少地)控制着数据的生命周期。默认情况下Hive会将这些表的数据存储在由配置项 hive.metastore.warehouse.dir(例如,/user/hive/warehouse)所定义的目录的子目录下。 当删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享 数据。

案例:创建一个原始表

1)创建数据文件

vim student.txt

1001 student-1

1002 student-2

1003 student-3

1004 student-4

1005 student-5

1006 student-6

1007 student-7

1008 student-8

1009 student-9

1010 student-10

2)创建表

create table if not exists student( id int, name string )

row format delimited fields terminated by '\t'

stored as textfile;

3)导入数据

hdfs dfs -put datas/student.txt /user/hive/warehouse/student/

4)查询数据

5)查询表的类型

desc formatted 表名;

6)根据查询结果创建表

查询的结果会添加到新创建的表中

create table if not exists 新的表名 as select id, name from 查询的表名;

7)根据已经存在的表结构创建表

create table if not exists 新表名 like 克隆的表名;

8)删除表

drop table 表名;

表的数据和元数据都会删除

(3)外部表

Hive 并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据描述表的元数据信息会被删除掉

案例:创建一个外部表

1)创建表

create external table if not exists student4( id int, name string )

row format delimited fields terminated by '\t';

2)导入数据

hdfs dfs -put datas/student.txt /user/hive/warehouse/student4/

3)查询表的类型

4)删除外部表

drop table student4;

元数据被删除,但是hdfs的数据还会存在

(4)内与外部表的互相转换

1)修改内部表为外部表

alter table 表名 set tblproperties('EXTERNAL'='TRUE');

2)修改外部表为内部表

alter table 表名 set tblproperties('EXTERNAL'='FALSE');

注意:('EXTERNAL'='TRUE')和('EXTERNAL'='FALSE')为固定写法,区分大小写!

7、修改表

(1)修改表名

ALTER TABLE table_name RENAME TO new_table_name

(2)操作列

注意:对列的操作只会对元数据进行修改,不会改hdfs里的数据

1)新增列

ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment], ...)

例如: alter table 表名 add columns (列名 列类型, ...)

增加一列班级class

2)更新列

ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]

例如:alter table 表名 change 旧列名 新列名 列类型;

修改class列名为class_name

  • 必须要写数据类型,否则会报错
  • 小范围类型可以向大范围类型转换,反之不可以

例如 int可以转string,但string不可以转int

3)替换列

ALTER TABLE table_name REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)

注意是将整个表的结构替换

  • 将class_name 替换成 class
4)删除列

可以使用 REPLACE 删除列,也可以使用 REPLACE 增加列

例如: 删除class 增加 address

(3)删除表

drop table 表名;

五、DML数据操作

1、数据导入

(1)加载数据Load

1)语法

load data [local] inpath '数据的路径' [overwrite] into table table_name [partition (partcol1=val1,...)];

语句说明:

  • **load data:**表示加载数据
  • **local:**表示从本地加载数据到hive表;否则从HDFS加载数据到hive表
  • **inpath:**表示加载数据的路径
  • **overwrite:**表示覆盖表中已有数据,否则表示追加
  • **into table:**表示加载到哪张表
  • **table_name:**表示具体的表
  • **partition:**表示上传到指定分区
2)加载本地文件到hive

load data local inpath '本地文件地址' into table 表名;

3)加载HDFS文件到hive中

上传数据到hdfs

dfs -put '本地文件位置' hdfs文件位置;

加载HDFS上数据到hive

load data inpath 'hdfs文件位置' into table default.表名;

4)覆盖表中数据

load data inpath 'hdfs文件位置' overwrite into table 表名;

(2)插入数据Insert

1)基本插入

insert into table 表名 values(字段值, ...),(字段值, ...);

2)单表查询结果插入

insert [overwrite] table 表名 select 字段名 from 表名 [where 条件];

insert into:以追加数据的方式插入到表或分区,原有数据不会删除

insert overwrite:会覆盖表中已存在的数据

注意:insert 不支持插入部分字段

3)查询结果插入多表

from 查询的表名

insert overwrite table 插入的表名1

select 查询的字段名

insert overwrite table 插入的表名2

select 查询的字段名;

(3)查询中创建表As Select

查询语句中创建表并加载数据(As Select)

create table if not exists 新建的表名 as select 字段 from 查询的表名;

2、数据导出

(1)Insert 导出

1)将查询的结果导出到本地

insert overwrite local directory '本地目录' select * from 表名;

2)将查询的结果格式化导出到本地

insert overwrite local directory '本地目录'

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'

select * from 表名;

3)将查询的结果导出到HDFS上

insert overwrite directory 'hdfs目录'

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'

select * from 表名;

(2)Hadoop导出本地

dfs -get hdfs文件路径 本地文件路径;

(3)Hive Shell命令导出

bin/hive -e '查询语句' > 本地文件路径;

3、清除表中数据

注意:Truncate只能删除管理表的数据,不能删除外部表中数据

truncate table 表名;

六、查询

官网文档https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Select

SELECT [ALL | DISTINCT] select_expr, select_expr, ...

FROM table_reference

WHERE where_condition

GROUP BY col_list

ORDER BY col_list

CLUSTER BY col_list \| \[DISTRIBUTE BY col_list\] \[SORT BY col_list

]

LIMIT number

数据准备:

(1)创建部门表:

sql 复制代码
create table if not exists dept( 
    deptno int, 
    dname string, 
    loc int 
)
row format delimited fields terminated by '\t';

创建数据 dept.txt

sql 复制代码
10	ACCOUNTING	1700 
20	RESEARCH	1800 
30	SALES	1900 
40	OPERATIONS	1700

导入数据

load data local inpath '/opt/module/hive/datas/dept.txt' into table dept;

(2)创建员工表:

sql 复制代码
create table if not exists emp( 
	empno int, 
	ename string, 
	job string, 
	mgr int, 
	hiredate string,  
	sal double,  
	comm double, 
	deptno int
)
row format delimited fields terminated by '\t';

创建数据 emp.txt

sql 复制代码
7369    SMITH   CLERK   7902    1980-12-17      800.00  20
7499    ALLEN   SALESMAN        7698    1981-2-20       1600.00 300.00  30
7521    WARD    SALESMAN        7698    1981-2-22       1250.00 500.00  30
7566    JONES   MANAGER 7839    1981-4-2        2975.00         20
7654    MARTIN  SALESMAN        7698    1981-9-28       1250.00 1400.00 30
7698    BLAKE   MANAGER 7839    1981-5-1        2850.00         30
7782    CLARK   MANAGER 7839    1981-6-9        2450.00         10
7788    SCOTT   ANALYST 7566    1987-4-19       3000.00         20
7839    KING    PRESIDENT               1981-11-17      5000.00         10
7844    TURNER  SALESMAN        7698    1981-9-8        1500.00 0.00    30
7876    ADAMS   CLERK   7788    1987-5-23       1100.00         20
7900    JAMES   CLERK   7698    1981-12-3       950.00          30
7902    FORD    ANALYST 7566    1981-12-3       3000.00         20
7934    MILLER  CLERK   7782    1982-1-23       1300.00         10

导入数据

load data local inpath '/opt/module/hive/datas/emp.txt' into table emp;

1、基本查询

(1)全表查询

select * from 表名;

(2)指定列查询

select 列名, 列名, ... from 表名;

注意:

  • SQL 语言大小写不敏感。
  • SQL 可以写在一行或者多行
  • 关键字不能被缩写也不能分行
  • 各子句一般要分行写。
  • 使用缩进提高语句的可读性。

(3)列别名

紧跟列名,加入关键字'AS'

select 列名 别名, 列名 as 别名, ... from 表名;

(4)算术运算符

|------|-----------|
| 运算符 | 描述 |
| A+B | A 和B 相加 |
| A-B | A 减去B |
| A*B | A 和B 相乘 |
| A/B | A 除以B |
| A%B | A 对B取余 |
| A&B | A 和B按位取与 |
| A|B | A 和B按位取或 |
| A^B | A 和B按位取异或 |
| ~A | A 按位取反 |

(5)常用函数

1)总行数count()

select count(*) cnt from 表名;

2)最大值max()

select max(字段) from 表名;

3)最小值min()

select min(字段) from 表名;

4)总和sum()

select sum(字段) from 表名;

5)平均值avg()

select avg(字段) from 表名;

(6)Limit 语句

用于限制返回的行数

select 字段名 from 表名 limit 行数;

select 字段名 from 表名 limit 开始行, 取N条;

(7)Where语句

WHERE子句紧随FROM子句,使用WHERE子句,将不满足条件的行过滤掉

查询出薪水大于1000的所有员工

select * from emp where sal >1000;

(8)比较运算符

|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 操作符 | 描述 |
| A=B | 如果A等于B则返回TRUE,反之返回FALSE 例如:price = 100 |
| A<==>B | 如果A和B都为NULL,则返回TRUE,如果一边为NULL, 返回False |
| A<>B 或 A != B | A或者B为NULL,则返回NULL;如果A不等于B,则返回 TRUE,反之返回FALSE |
| A < B | A或者B为NULL,则返回NULL;如果A小于B,则返回 TRUE,反之返回FALSE |
| A <= B | A或者B为NULL,则返回NULL;如果A小于等于B,则返 回TRUE,反之返回FALSE |
| A > B | A或者B为NULL,则返回NULL;如果A大于B,则返回 TRUE,反之返回FALSE |
| A >= B | A或者B为NULL,则返回NULL;如果A大于等于B,则返 回TRUE,反之返回FALSE |
| A [NOT] BETWEEN B AND C | 如果A,B或者C任一为NULL,则结果为NULL。如果A的 值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。 如果使用NOT关键字则可达到相反的效果。 |
| A IS NULL | 如果A等于NULL,则返回TRUE,反之返回FALSE |
| A IS NOT NULL | 如果A不等于NULL,则返回TRUE,反之返回FALSE |
| IN(数值1, 数值2) | 使用 IN运算显示列表中的值 |
| A [NOT] LIKE B | B是一个SQL下的简单正则表达式,也叫通配符模式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。 B的表达式 说明如下: 'x%':表示A必须以字母'x'开头, '%x':表示A 必须以字母'x'结尾, '%x%':表示A包含有字母'x',可以 位于开头,结尾或者字符串中间。 如果使用NOT关键字则可达到 相反的效果。 |
| A RLIKE B A REGEXP B | B是基于java的正则表达式,如果A与其匹配,则返回 TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。 例如,正则表达式必须和 整个字符串A相匹配,而不是只需与其字符串匹配。 |

上面操作符可以用于JOIN...ON和HAVING语句中

1)查询出薪水等于5000的所有员工

select * from emp where sal =5000;

2)查询工资在500到1000的员工信息

select * from emp where sal between 500 and 1000;

3)查询comm为空的所有员工信息

select * from emp where comm is null;

4)查询工资是1500或5000的员工信息

select * from emp where sal IN (1500, 5000);

(9)Like 和 RLike

RLIKE 子句是 Hive 中这个功能的一个扩展,其可以通过 Java 的正则表达式这个更强大 的语言来指定匹配条件。

% 代表零个或多个字符(任意个字符)。

_ 代表一个字符。

1)查找名字以A开头的员工信息

select * from emp where ename LIKE 'A%';

2)查找名字中第二个字母为A的员工信息

select * from emp where ename LIKE '_A%';

3)查找名字中带有A的员工信息

select * from emp where ename RLIKE '[A]';

或者

select * from emp where ename RLIKE '%A%';

(10)逻辑运算符

|-----|-----|
| 操作符 | 含义 |
| AND | 逻辑并 |
| OR | 逻辑或 |
| NOT | 逻辑否 |

1)查询薪水大于1000,部门是30

select * from emp where sal>1000 and deptno=30;

2)查询薪水大于1000,或者部门是30

select * from emp where sal>1000 or deptno=30;

3)查询除了20部门和30部门以外的员工信息

select * from emp where deptno not IN(30, 20);

2、分组

(1)Group By

GROUP BY 语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。

1)计算emp表每个部门的平均工资

select

deptno, avg(sal)

from emp
group by deptno;

2)计算emp每个部门中每个岗位的最高薪水

select

deptno, job, max(sal)

from emp
group by deptno, job;

(2)Having

having 与 where 不同点

  • where 后面不能写分组函数,而having后面可以使用分组函数。
  • having 只用于group by分组统计语句。

1)求每个部门的平均薪水大于2000的部门

select

deptno, avg(sal) avg_sal

from emp

group by deptno
havingavg_sal > 2000;

3、Join 语句

数据准备:插入一条员工数据,该员工不属于任何部门

insert into emp values(8000, 'lisi', 'CLERK', 7782, 2000-2-20, 2000, null, 50);

(1)表的别名

  • 使用别名可以简化查询。
  • 使用表名前缀可以提高执行效率。

(2)内连接

内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。

查询员工编号,员工名称和部门名称

select

e.empno, e.ename, d.dname

from emp e
joindept d on e.deptno = d.deptno;

emp表有15条数据,dept表有4条数据,最终只会查出两者公共的部分14条

(3)左外连接

左外连接:左边表中符合WHERE子句的所有记录将会被返回,右表不存在则填充null

查询员工编号,员工名称和部门名称

select

e.empno, e.ename, d.dname

from emp e
left join dept d on e.deptno = d.deptno;

(4)右外连接

右外连接:右边表中符合WHERE子句的所有记录将会被返回,左边表不存在则返回null

查询员工编号,员工名称和部门名称

select

e.empno, e.ename, d.dname

from emp e
right join dept d on e.deptno = d.deptno;

(5)满外连接

满外连接:将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值使用NULL值替代。

查询员工编号,员工名称,部门编号和部门名称

select

e.empno, e.ename, e.deptno , d.dname

from emp e
full join dept d on e.deptno = d.deptno;

此时发现在emp表中不存在这个部门,所以返回null,但是在部门表中是存在的

修改为如下语句:

select

e.empno, e.ename, d.deptno , d.dname

from emp e
full join dept d on e.deptno = d.deptno;

此时发现在emp表中存在这个部门编号,但是在部门表中不存在部门编号

终极修改为如下语句:

select

e.empno,

e.ename,

nvl(d.deptno, e.deptno),

d.dname

from emp e
full join dept d

on e.deptno = d.deptno;

(6)左排除连接

左排除连接:将会返回左表中符合WHERE语句条件的左表独有记录。

思路:可以将左外连接去除掉公共部分(右为null)

select

e.empno, e.ename, d.deptno , d.dname

from emp e
left join dept d on e.deptno = d.deptno

where d.deptno is null;

或者

select

empno, ename, deptno

from emp

where

deptno not in (

select deptno

from dept

);

此方法极不推荐

(7)右排除连接

右排除连接:将会返回右表中符合WHERE语句条件的右表独有记录。

思路:可以将右外连接去除掉公共部分(左为null)

select

d.deptno, d.dname

from emp e
right join dept d on e.deptno = d.deptno

where

e.deptno is null;

(8)外部排除连接

外部排除连接:将会返回左表独有记录和右表独有记录。

思路:根据满外连接,条件为 左表为null或者右表为null的数据

select

e.empno, e.ename, e.deptno,

d.deptno, d.dname

from emp e
full join dept d on d.deptno = e.deptno
where e.deptno is null or d.deptno is null;

或者使用左外连接和右外连接,在通过 union查询,

select

*

from (

select

e.empno, e.ename, e.deptno e_deptno,

d.deptno d_deptno, d.dname

from emp e

left join dept d on d.deptno = e.deptno

where d.deptno is null

union

select

e.empno, e.ename, e.deptno e_deptno,

d.deptno d_deptno, d.dname

from emp e

right join dept d on d.deptno = e.deptno

where e.deptno is null

) edp;

union和union all 的区别

  • union 会去重
  • union all 不会去重

(9)多表连接查询

1)数据准备

创建文件loc.txt

1700 Beijing

1800 London

1900 Tokyo

2)创建表

create table if not exists location(

loc int,

loc_name string

)

row format delimited fields terminated by '\t';

3)导入数据

load data local inpath '/opt/module/hive/datas/loc.txt' into table location;

4)多表查询

select

e.ename, d.dname, l.loc_name

from emp e

join dept d on d.deptno = e.deptno

join location l on l.loc = d.loc;

大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先 启动一个MapReduce job 对表e和表d进行连接操作,然后会再启动一个MapReduce job将 第一个MapReduce job 的输出和表l;进行连接操作。

(10)笛卡尔积

产生的条件

  • 省略连接条件
  • 连接条件无效
  • 所有表中的所有行互相连接
    select empno, dname from emp, dept;

4、排序

(1)全局排序(Order By)

Order By:全局排序,只有一个Reducer,ORDER BY 子句在 SELECT 语句的结尾。

ASC(ascend): 升序(默认)

DESC(descend): 降序

1)查询员工信息按工资升序排列

select * from emp order by sal

2)查询员工信息按工资降序排列

select * from emp order by sal desc;

3)按照别名排序

按照员工薪水的2倍排序

select ename, sal * 2 twosal from emp order by twosal;

4)多个列排序

按照部门和工资升序排序

select ename, deptno, sal from emp order by deptno, sal;

(2)内部排序(Sort By)

对于大规模的数据集order by的效率非常低。在很多情况下,并不需要全局排序,此时可以使用sort by。 Sort by 为每个reducer 产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。

1)查看设置reduce个数

set mapreduce.job.reduces;

-1表示不设置reduce数量,根据配置自动分配

2)设置reduce个数

set mapreduce.job.reduces=3;

3)根据部门编号降序查看员工信息

select ename, deptno, sal from emp sort by deptno desc;

4)将查询结果导入到文件中(按照部门编号降序排序)

insert overwrite local directory '/opt/module/hive/datas/sortby-result'

row format delimited fields terminated by '\t'

select ename, deptno, sal from emp sort by deptno desc;

(3)分区(Distribute By)

在有些情况下需要控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。distribute by 子句可以做这件事。distribute by类似MR中partition(自定义分区),进行分区,结合sort by使用。

对于distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到distribute by 的效果。

先按照部门编号分区,再按照员工编号降序排序

set mapreduce.job.reduces=3;

insert overwrite local directory '/opt/module/hive/datas/distribute-result'

row format delimited fields terminated by '\t'

select empno, ename, deptno, sal from emp distribute by deptno sort by empno desc;

注意:

  • distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后, 余数相同的分到一个区。
  • Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。

(4)Cluster By

当distribute by的字段 和 sorts by 字段相同时,可以使用cluster by 方式。

cluster by 除了具有 distribute by 的功能外还兼具 sort by 的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

以下两种写法等价:

select * from emp cluster by deptno;

select * from emp distribute by deptno sort by deptno;

注意:按照部门编号分区,不一定就是固定死的数值,可以是20号和30号部门分到一 个分区里面去。

insert overwrite local directory '/opt/module/hive/datas/cluster-result'

row format delimited fields terminated by '\t'

select empno, ename, deptno, sal from emp cluster by deptno;

七、分区表和分桶表

1、分区表

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据 集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

(1)基本操作

1)创建分区表

a、创建表

create table dept_partition(

deptno int,

dname string,

loc string

)

partitioned by (day string)

row format delimited fields terminated by '\t';

注意:分区字段不能是表中已经存在的字段,可以将分区字段看作表的伪列。

b、数据准备

dept-1.txt

10 ACCOUNTING 1700

20 RESEARCH 1800

dept-2.txt

30 SALES 1900

40 OPERATIONS 1700

dept-3.txt

50 TEST 2000

60 DEV 1900

c、加载数据

load data local inpath '/opt/module/hive/datas/dept-1.txt'

into table dept_partition partition(day='2026-03-24');

load data local inpath '/opt/module/hive/datas/dept-2.txt'

into table dept_partition partition(day='2026-03-23');

load data local inpath '/opt/module/hive/datas/dept-3.txt'

into table dept_partition partition(day='2026-03-22');

注意:分区表加载数据时,必须指定分区

2)查询数据

a、单分区查询

select * from dept_partition where day='2026-03-22';

b、多分区联合查询

select * from dept_partition where day='2026-03-22'

union

select * from dept_partition where day='2026-03-23'

union

select * from dept_partition where day='2026-03-24';

或者

select * from dept_partition

where day='2026-03-22' or day='2026-03-23' or day='2026-03-24';

3)增加分区

a、创建单个分区

alter table dept_partition add partition(day='2026-03-25');

b、创建多个分区

alter table dept_partition add partition(day='2026-03-26') partition(day='2026-03-27');

注意:多个分区中间用空格隔开

4)删除分区

a、删除单个分区

alter table dept_partition drop partition (day='2026-03-25');

b、 删除多个分区

alter table dept_partition drop partition (day='2026-03-26'), partition(day='2026-03-27');

注意:删除多个分区中间用逗号隔开

5)查看分区

查看分区表有多少分区

show partitions dept_partition;

6)查看分区表结构

desc formatted dept_partition;

(2)二级分区

1)创建二级分区表

create table dept_partition2(

deptno int,

dname string,

loc string

)

partitioned by (day string, hour string)

row format delimited fields terminated by '\t';

2)加载数据

(1)加载数据到二级分区表中

load data local inpath '/opt/module/hive/datas/dept-1.txt'

into table dept_partition2 partition(day='2026-03-24', hour='12');

load data local inpath '/opt/module/hive/datas/dept-2.txt'

into table dept_partition2 partition(day='2026-03-24', hour='13');

load data local inpath '/opt/module/hive/datas/dept-3.txt'

into table dept_partition2 partition(day='2026-03-25', hour='12');

(2)查询分区数据

select * from dept_partition2 where day='2026-03-24' and hour='12';

3)分区表和数据产生关联

方式一:上传数据后修复

上传数据

dfs -mkdir -p /user/hive/warehouse/dept_partition2/day=2026-03-24/hour=14;

dfs -put /opt/module/hive/datas/dept-1.txt /user/hive/warehouse/dept_partition2/day=2026-03-24/hour=14;

查询数据

select * from dept_partition2 where day='2026-03-24' and hour='14';

发现无法查询到数据,原因是元数据没有对应的分区信息

执行修复命令

msck repair table dept_partition2;

再次查询数据

方式二:上传数据后添加分区

上传数据

dfs -mkdir -p /user/hive/warehouse/dept_partition2/day=2026-03-24/hour=15;

dfs -put /opt/module/hive/datas/dept-1.txt /user/hive/warehouse/dept_partition2/day=2026-03-24/hour=15;

执行添加分区

alter table dept_partition2 add partition(day='2026-03-24',hour='15');

查询数据

select * from dept_partition2 where day='2026-03-24' and hour='15';

方式三:load数据到分区

创建目录

dfs -mkdir -p /user/hive/warehouse/dept_partition2/day=2026-03-24/hour=16;

上传数据

load data local inpath '/opt/module/hive/datas/dept-1.txt' into table dept_partition2 partition(day='2026-03-24',hour='16');

查询数据

select * from dept_partition2 where day='2026-03-24' and hour='16';

(3)动态分区调整

1)开启动态分区参数设置

a、开启动态分区功能(默认true,开启)

hive.exec.dynamic.partition=true;

b、设置为非严格模式

动态分区的模式:

  • strict:默认,表示必须指定至少一个分区为静态分区
  • nonstrict:表示允许所有的分区字段都可以使用动态分区。
    hive.exec.dynamic.partition.mode=nonstrict;

c、最大分区数

在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000

hive.exec.max.dynamic.partitions=1000

d、每个节点最大分区数

在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。

hive.exec.max.dynamic.partitions.pernode=100

e、最大HDFS文件数

整个MR Job中,最大可以创建多少个HDFS文件。默认100000

hive.exec.max.created.files=100000

f、空分区异常

当有空分区生成时,是否抛出异常。一般不需要设置。默认false

hive.error.on.empty.partition=false

2)案例

创建目标分区表

create table dept_partition_dy(id int, name string)

partitioned by (loc int)

row format delimited fields terminated by '\t';

设置动态分区

set hive.exec.dynamic.partition.mode = nonstrict;

插入数据

insert into table dept_partition_dy partition(loc) select deptno, dname, loc from dept;

查看目标分区表的分区情况

show partitions dept_partition_dy;

2、分桶表

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理 的分区。对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围 划分。 分桶是将数据集分解成更容易管理的若干部分的另一个技术。 分区针对的是数据的存储路径;分桶针对的是数据文件。

(1)创建分桶表

1)数据准备

student.txt

1001 lisi-1

1002 lisi-2

1003 lisi-3

1004 lisi-4

1005 lisi-5

1006 lisi-6

1007 lisi-7

1008 lisi-8

1009 lisi-9

1010 lisi-10

1011 lisi-11

1012 lisi-12

1013 lisi-13

1014 lisi-14

1015 lisi-15

1016 lisi-16

2)创建分桶表

create table stu_buck(id int, name string)

clustered by(id)

into 4 buckets

row format delimited fields terminated by '\t';

3)查看表结构

desc formatted stu_buck;

4)导入数据

本地文件

load data local inpath '/opt/module/hive/datas/student.txt' into table stu_buck;

hdfs文件

load data inpath '/student.txt' into table stu_buck;

5)查询分桶的数据

select * from stu_buck;

发现数据是无序的

6)分桶规则

根据结果可知:Hive的分桶采用对分桶字段的值进行哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中

(2)注意的事项

1)reduce 的个数设置为-1,让 Job 自行决定需要用多少个reduce或者将reduce 的个 数设置为大于等于分桶表的桶数

2)从hdfs中load数据到分桶表中,避免本地文件找不到问题

3)不要使用本地模式

(3)insert导入数据

insert 方式将数据导入分桶表

insert into table stu_buck select * from student_insert;

3、抽样查询

对于非常大的数据集,有时需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。

语法: TABLESAMPLE(BUCKET x OUT OF y)

查询表stu_buck 中的数据。

select * from stu_buck tablesample(bucket 1 out of 4 on id);

注意:x的值必须小于等于y的值

相关推荐
旺仔小拳头..21 小时前
Servlet概念与创建
数据仓库·hive·hadoop
旺仔小拳头..1 天前
Filter 过滤器 与Listener 监听器
数据仓库·hive·hadoop
Leo.yuan1 天前
实时ETL怎么做?有哪些好用的ETL工具?
数据仓库·etl
晨晖21 天前
Servlet的快速入门,请求和响应
hive·hadoop·servlet
AllData公司负责人1 天前
AllData数据中台通过集成DolphinScheduler+Seatunnel实现SAP HANA数据库同步到Doris数据仓库
数据库·数据仓库·sap hana
yumgpkpm1 天前
AI算力纳管工具GPUStack Server+华为鲲鹏+麒麟操作系统 保姆级安装过程
人工智能·hadoop·华为
`林中水滴`1 天前
【数据仓库】Iceberg、Hudi、Delta Lake、Paimon:四大开源湖表格式怎么选?
数据仓库
黄昏回响1 天前
计算机系统基础知识(补充篇):数据库——数据仓库、数据中台与大数据技术详解
大数据·数据库·数据仓库
hellolianhua1 天前
测试集群hdfs和mapreduce
大数据·hadoop·hdfs