hive基础文档

Hive
Hive简介
Hive:由 Facebook 开源用于解决海量结构化日志的数据统计工具。
Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类 SQL 查询功能
Hive 本质:将 HQL 转化成 MapReduce 程序
(1)Hive 处理的数据存储在 HDFS
(2)Hive 分析数据底层的实现是 MapReduce
(3)执行程序运行在 Yarn 上

Hive的优缺点
优点:
(1)操作接口采用类 SQL 语法,提供快速开发的能力(简单、容易上手)。
(2)避免了去写 MapReduce,减少开发人员的学习成本。
(3)Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合。
(4)Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高。
(5)Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
缺点:
1)Hive 的 HQL 表达能力有限
(1)迭代式算法无法表达
(2)数据挖掘方面不擅长,由于 MapReduce 数据处理流程的限制,效率更高的算法却无法实现。
2)Hive 的效率比较低
(1)Hive 自动生成的 MapReduce 作业,通常情况下不够智能化
(2)Hive 调优比较困难,粒度较粗
Hive的特点:
1.通过sql访问数据,支持数仓etl任务,报表,数据分析
2.对各种数据格式施加结构的一种机制
3.直接访问hdfs或者其他数据存储系统如hbase
4.通过 Apache Tez、 Apache Spark 或 MapReduce 执行查询
5.压秒级查询通过 Hive LLAP, Apache YARN and Apache Slider.
6.Hive可以使用jdbc连接
7.Hive可以对元数据进行权限管理

Hive架构
在这里插入图片描述

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

在这里插入图片描述

Hive和传统关系型数据库比较
查询语言:专门针对Hive的特性设计了类SQL的查询语言HQL与SQL差别不大,熟悉SQL的开发者,可以很方便的使用hive开发。
在这里插入图片描述

Hive查询慢的原因:
1.查询数据数据,每次都需要扫描所有数据,磁盘IO耗时高
2.MapReduce本身具有较高的延迟。
hive安装(3.1.0)
1.解压文件至指定目录
tar -zvxf /data/package/apache-hive-3.1.0-bin.tar.gz -C /data/soft/
2.创建日志存放目录
mkdir -p /data/soft/apache-hive-3.1.0-bin/logs
3.进入hive配置文件目录
cd /data/soft/apache-hive-3.1.0-bin/conf
4.得到hive-env.sh文件
cp hive-env.sh.template hive-env.sh
5.修改hive-env.sh文件
vi hive-env.sh
在这里插入图片描述

HADOOP_HOME=/data/soft/hadoop-3.2.1
export HIVE_CONF_DIR=/data/soft/apache-hive-3.1.0-bin/conf

6.修改hive-site.xml文件(注意修改用户名、密码和url)
vi ./hive-site.xml
在这里插入图片描述

<configuration>
  <property>
          <name>javax.jdo.option.ConnectionUserName</name>
          <value>root</value>
  </property>
  <property>
          <name>javax.jdo.option.ConnectionPassword</name>
          <!--你的Mysql数据库密码-->
          <value>123456</value>
  </property>
  <property>
          <name>javax.jdo.option.ConnectionURL</name>
          <value>jdbc:mysql://localhost:3306/hive?allowMultiQueries=true&amp;useSSL=false&amp;verifyServerCertificate=false</value>
  </property>
  <property>
          <name>javax.jdo.option.ConnectionDriverName</name>
          <value>com.mysql.jdbc.Driver</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>
<!-- hiveserver2用户名 -->
   <property>
        <name>beeline.hs2.connection.user</name>
        <value>root</value>
   </property>
   <!-- hiveserver2密码 -->
   <property>
        <name>beeline.hs2.connection.password</name>
        <value>tsgs@2912A!</value>
   </property>
<!-- 指定 hiveserver2 连接的端口号 --> 
<property> 
<name>hive.server2.thrift.port</name> 
<value>10000</value> 
</property> 

</configuration>
  1. 修改hive日志配置文件(修改日志存放目录)
    cp hive-log4j2.properties.template hive-log4j2.properties
    vi hive-log4j2.properties
    在这里插入图片描述

8.将mysql的驱动包,拷贝至hive/lib目录下
mysql-connector-java-5.1.46.jar
在这里插入图片描述

9.用hadoop高版本的guava-27.0-jre.jar替换hive低版本的包
cp /data/soft/hadoop-3.2.1/share/hadoop/common/lib/guava-27.0-jre.jar /data/soft/apache-hive-3.1.0-bin/lib/
rm -rf /data/soft/apache-hive-3.1.0-bin/lib/guava-19.0.jar
10.mysql创建hive数据库
11.初始化hive:
./bin/schematool -dbType mysql -initSchema
在这里插入图片描述
在这里插入图片描述

看见schemaTool completed,表示初始化成功

12.验证:
hive命令验证:
在这里插入图片描述

元数据存储——Metastore
Hive有三种Metastore的配置方式:内嵌模式、本地模式、远程模式
内嵌模式:
使用内嵌的Derby数据库来存储数据,配置简单,但是一次只能与一个客户端连接,适用于单元测试,不适用于生产环境,如果采用多连接需要进行切换目录。
搭建:修改 ~/HIVE_HOME/conf/hive-site.xmd

在这里插入图片描述

本地模式:
需要使用外部数据库来存数据,比如mysql,本地模式下需要在本地运行一个mysql服务。
在这里插入图片描述

和远程模式:
都使用外部数据库来存数据。它们两者的区别在于本地模式元数据不需要单独启动Metastore服务,因为本地元存储用的是和本地Hive在同一个进程里的

元数据存储表说明
DBS:存储Hive中所有数据库的基本信息;
DATABASE_PARAMS:存储数据库的相关参数,在CREATE DATABASE时候用
WITH DBPROPERTIES (property_name=property_value, …)指定的参数;
TBLS:存储Hive表、视图、索引表的基本信息;
TABLE_PARAMS:存储表/视图的属性信息;
TBL_PRIVS:存储表/视图的授权信息;
SDS:保存文件存储的基本信息,如INPUT_FORMAT、OUTPUT_FORMAT、是否压缩等;
SD_PARAMS:存储Hive存储的属性信息;
SERDES:存储序列化使用的类信息;
SERDE_PARAMS:存储序列化的一些属性、格式信息,比如:行、列分隔符;
COLUMNS_V2:存储表对应的字段信息;
PARTITIONS:存储表分区的基本信息;
PARTITION_KEYS:存储分区的字段信息;
PARTITION_KEY_VALS:存储分区字段值;
PARTITION_PARAMS:存储分区的属性信息;
Metastore服务
内嵌模式(Embedded)
连接到一个In-memory的数据库Derby,一般是用于做单元测试
本地模式(Local)
通过网络连接到一个数据库中,这个是常用的一种模式
远程模式(Remote)
用于非JAVA客户端访问元数据库,在服务器端会启动MetaStoreServer,客户端通过Thrift协议及MetaStoreServer来访问元数据库
Hive使用
Hive启动:
命令行启动:
root@datacenter01 bin]# hive
Beelilne启动:
hiveserver启动:
./bin/hive --service metastore 1>/dev/null 2>&1 &
./bin/hive --service hiveserver2 1>/dev/null 2>&1 &
Hiveserver2脚本

#!/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

连接beeline

./bin/beeline  -u jdbc:hive2://datacenter01:10000 -n root

简单使用

hive> show databases; 
hive> show tables; 
hive> create table test(id string); 
hive> insert into test values('1'); 
hive> select * from test; 

Hive 常用命令
执行查询语句

hive -e "select * from hive.test"; 

将查询结果保存到本地文件

hive -e "select * from tmp.test" > /tmp/myquery 

查询warehouse相关set命令

hive -S -e "set" | grep warehouse 

执行sql文件

hive -f /root/1.sql
Hive> source /path/to/file/withqueries.hql

退出hive窗口

hive(default)>exit; 
hive(4default)>quit; 
Beeline>!q

查看hdfs文件系统

hive(default)>dfs -ls /; 

查看hive中所有历史命令

[root@datacenter01 ~]#cat /root/.hivehistory

查看当前所有配置信息

hive>set;

Hive切换队列的三种方式:

set mapred.job.queue.name=queue3;
SET mapreduce.job.queuename=queue3;
set mapred.queue.names=queue3;

HIVE 设置任务名称

set mapred.job.name = my_job_name

Hive参数配置
(1)配置文件方式
默认配置文件:hive-default.xml
用户自定义配置文件:hive-site.xml
注意:用户自定义配置会覆盖默认配置。另外,Hive 也会读入 Hadoop 的配置,因为 Hive
是作为 Hadoop 的客户端启动的,Hive 的配置会覆盖 Hadoop 的配置。配置文件的设定对本机启动的所有 Hive 进程都有效。
(2)命令行参数方式
启动 Hive 时,可以在命令行添加-hiveconf param=value 来设定参数。
例如:
[root@datacenter01]$ 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配置解析:
hive.cli.print.header=true 显示表头
hive.cli.print.current.db=true 显示当前库
hive.exec.dynamic.partition=true 开启动态分区
hive.exec.dynamic.partition.mode=nonstrict 设置动态分区格式所有分区都可以为动态分区
hive.exec.max.dynamic.partitions=1000 最大可创建动态分区为1000个
hive.exec.max.dynamic.partitions.pernode=100 每个MR最大可以创建100个分区,默认100
hive.exec.max.created.files=100000 整个MR最大可创建多个个分区,默认100000
hive.error.on.empty.partition=false 当有空分区是是否抛异常,默认false
hive.exec.compress.intermediate=true; 开启 hive 中间传输数据压缩功能
mapreduce.map.output.compress=true; 开启 hive 中间传输数据压缩功能
mapreduce.map.output.compress=true; 开启 mapreduce 中 map 输出压缩功能
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec; 设置 mapreduce 中 map 输出数据的压缩方式
set hive.exec.compress.output=true; 开启 hive 最终输出数据压缩功能
mapreduce.output.fileoutputformat.compress=true; 开启 mapreduce 最终输出数据压缩
mapreduce.output.fileoutputformat.compress.codec =
org.apache.hadoop.io.compress.SnappyCodec; 设置 mapreduce 最终数据输出压缩方式
mapreduce.output.fileoutputformat.compress.type=BLOCK; 设置 mapreduce 最终数据输出压缩为块压缩
hive.auto.convert.join = true 默认值为true,自动开户MAPJOIN优化
hive.mapjoin.smalltable.filesize=25000000; 默认值为2500000(25M),通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中数据量预估

Hive数据类型
基本数据类型
在这里插入图片描述

对于 Hive 的 String 类型相当于数据库的 varchar 类型,该类型是一个可变的字符串,不
过它不能声明其中最多能存储多少个字符,理论上它可以存储 2GB 的字符数。
集合数据类型
在这里插入图片描述

Hive 有三种复杂数据类型 ARRAY、MAP 和 STRUCT。ARRAY 和 MAP 与 Java 中的 Array
和 Map 类似,而 STRUCT 与 C 语言中的 Struct 类似,它封装了一个命名字段集合,复杂数据
类型允许任意层次的嵌套。
案例实操
(1)假设某表有如下一行,我们用 JSON 格式来表示其数据结构。在 Hive 下访问的格
式为

{ 
"name": "songsong", 
"friends": ["bingbing" , "lili"] , //列表 Array, 
"children": { //键值 Map, 
"xiao song": 18 , 
"xiaoxiao song": 19 
} 
"address": { //结构 Struct, 
"street": "hui long guan", 
"city": "beijing" 
} 
} 

(2)基于上述数据结构,我们在 Hive 里创建对应的表,并导入数据。
创建本地测试文件 test.txt

songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long 
guan_beijing 
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing 

注意:MAP,STRUCT 和 ARRAY 里的元素间关系都可以用同一个字符表示,这里用“_”。
(3)Hive 上创建测试表 test

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'; -- 行分隔符

(4)导入文本数据到测试表

load data local inpath '/root/tmp/test.txt' into table ; 

(5)访问三种集合列里的数据,以下分别是 ARRAY,MAP,STRUCT 的访问方式

hive (default)> select friends[1],children['xiao song'],address.city from 
test 
where name="songsong";

sqoop将hive数据导出到myql乱码问题解决
进入myql 执行 show variables like ‘character%’; 看到如下:
在这里插入图片描述

方法一:
执行如下两个命令即可:

set character_set_database=utf8;
set character_set_server=utf8;

方法二:
1.进入 my.cnf文件(vi /et/my.cnf) ,修改如下配置:

character_set_server=utf8mb4
init_connect='SET NAMES utf8'
collation-server=utf8_unicode_ci
character-set-server=utf8
skip-character-set-client-handshake

2.重启mysql服务
service mysqld restart 或 systemctl restart msyqld
注意:connect 连接的地址加上了 ?useUnicode=true&characterEncoding=utf-8

Hive表字段和分区中文注释乱码解决
进入hive元数据库

①修改表字段注解和表注解
alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8
alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8
② 修改分区字段注解:
alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8 ;
alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;
③修改索引注解:
alter table INDEX_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;

hive分隔符
row format delimited 分隔符设置开始语句
fields terminated by:设置字段与字段之间的分隔符
collection items terminated by:设置一个复杂类型(array,struct)字段的各个item之间的分隔符
map keys terminated by:设置一个复杂类型(map)字段的key value之间的分隔符
lines terminated by:设置行与行之间的分隔符
注意:hive表字段分割尽量避免单独使用这些符号, @ \t \n \r % ,# ¥ $ ^ & * ~ ` = .|、±_ 如果使用的话 就组合使用
或使用特殊字符:
在这里插入图片描述

Hive数据导入导出

导入
–1.load方式向表中装载数据

load data [local] inpath '路径' [overwrite] into table 表名 [partition (分区字段=,)];

–例如:
–从本地加载数据到hive

load data local inpath '/home/hdfs/data/test.txt' into table test;

–2.从hdfs系统加载数据覆盖hive表

hive (default)> dfs -put /home/hdfs/data/test.txt /wcinput;
hive (default)> load data inpath '/wcinput/test.txt' overwrite into table test;

–3.查询方式插入数据

 INSERT INTO[overwrite] TABLE tablename1 [PARTITION(partcol1=val1, partcol2=val2 ...)]  select_statement1 FROM from_statement;

–4.建表方式导入数据
–查询建表方式

 create table if not exists 表名 as select_statement1 FROM from_statement;

–建表制定数据位置

 create database db_hive2 location '/db_hive2.db';

–5. import 方式导入

hive (default)> import table student2 
from '/user/hive/warehouse/export/student'; 

导出
–1. Insert方式,查询结果导出到本地或HDFS

Insert overwrite local directory '/root/insert/student' select id,name from student;
Insert overwrite directory '/user/ insert /student' select id,name from student;

–2.Hadoop命令导出本地

hive>dfs -get /user/hive/warehouse/student/ 000000_0 /root/hadoop/student.txt

–3.hive Shell命令导出

]$ bin/hive -e 'select id,name from student;' > /root/hadoop/student.txt

–4.Export导出到HDFS

hive>export table student to '/user/export/student';

–5. 将查询的结果格式化导出到本地

hive(default)>insert overwrite local directory 
'/opt/module/hive/data/export/student1' 
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' 
select * from student; 

类型转化
Hive 的原子数据类型是可以进行隐式转换的,类似于 Java 的类型转换,例如某表达式 使用 INT 类型,TINYINT 会自动转换为 INT 类型,但是 Hive 不会进行反向转化,例如,某表 达式使用 TINYINT 类型,INT 不会自动转换为 TINYINT 类型,它会返回错误,除非使用 CAST操作。
1)隐式类型转换规则如下
(1)任何整数类型都可以隐式地转换为一个范围更广的类型,如 TINYINT 可以转换成
INT,INT 可以转换成 BIGINT。
(2)所有整数类型、FLOAT 和 STRING 类型都可以隐式地转换成 DOUBLE。
(3)TINYINT、SMALLINT、INT 都可以转换为 FLOAT。
2)可以使用 CAST 操作显示进行数据类型转换
例如 CAST(‘1’ AS INT)将把字符串’1’ 转换成整数 1;如果强制类型转换失败,如执行
CAST(‘X’ AS INT),表达式返回空值 NULL

0: jdbc:hive2://hadoop102:10000> select '1'+2, cast('1'as int) + 2; 
+------+------+--+ 
| _c0 | _c1 | 
+------+------+--+ 
| 3.0 | 3 | 
+------+------+--+ 

DDl
数据库
创建一个数据库,数据库在 HDFS 上的默认存储路径是/user/hive/warehouse/*.db

hive (default)> create database db_hive; 

避免要创建的数据库已经存在错误,增加 if not exists 判断。(标准写法)

create database if not exists db_hive;

创建一个数据库,指定数据库在 HDFS 上存放的位置

hive (default)> create database db_hive2 location '/db_hive2.db'; 

显示数据库

hive> show databases; 

过滤显示查询的数据库

hive> show databases like '*hive*'; 

显示数据库信息

desc database db_hive; 

显示数据库详细信息,extended

desc database extended hive;

切换当前数据库

hive (default)> use db_hive; 

修改数据库
用户可以使用 ALTER DATABASE 命令为某个数据库的 DBPROPERTIES 设置键-值对属性值,
来描述这个数据库的属性信息

hive (default)> alter database db_hive 
set dbproperties('createtime'='20170830'); 

删除空数据库

hive>drop database db_hive2; 

如果删除的数据库不存在,最好采用 if exists 判断数据库是否存在

hive> drop database if exists db_hive2; 

如果数据库不为空,可以采用 cascade 命令,强制删除

hive> drop database db_hive cascade;


建表语法

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
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 允许用户复制现有的表结构,但是不复制数据。
Hive修改字段注释:

ALTER TABLE table_name CHANGE COLUMN muid muid_new STRING COMMENT '这里是列注释!';
例如:alter table tb_test change column id id string comment '用户号码';

Hive修改表注释:

ALTER TABLE table_name SET TBLPROPERTIES('comment' = '这是表注释!');

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

create table if not exists student( 
id int, name string 
) 
row format delimited fields terminated by '\t' 
stored as textfile 
location '/user/hive/warehouse/student'; 

根据查询结果创建表(查询的结果会添加到新创建的表中)
create table if not exists student2 as select id, name from student;
根据已经存在的表结构创建表

create table if not exists student3 like student; 

查询表的类型

hive (default)> desc formatted student2; 
Table Type: MANAGED_TABLE 

外部表
因为表是外部表,所以 Hive 并非认为其完全拥有这份数据。删除该表并不会删除掉这
份数据,不过描述表的元数据信息会被删除掉。
建表语句,创建外部表

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

查看表格式化数据

hive (default)> desc formatted dept; 
Table Type: EXTERNAL_TABLE 

管理表与外部表的互相转换
修改内部表 student2 为外部表

alter table student2 set tblproperties('EXTERNAL'='TRUE');

修改外部表 student2 为内部表

alter table student2 set tblproperties('EXTERNAL'='FALSE');

重命名表

ALTER TABLE table_name RENAME TO new_table_name 

增加/修改/替换列信息
更新列

ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name 
column_type [COMMENT col_comment] [FIRST|AFTER column_name] 
alter table dept change column deptdesc desc string;

增加和替换列

ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT 
col_comment], ...)
alter table dept add columns(deptdesc string);
alter table dept replace columns(deptno string, dname string, loc string); 

注:ADD 是代表新增一字段,字段位置在所有列后面(partition 列前),
REPLACE 则是表示替换表中所有字段。
删除表

hive (default)> drop table dept;

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

hive (default)> create table dept_partition( 
deptno int, dname string, loc string
) 
partitioned by (day string) 
row format delimited fields terminated by '\t'; 

注意:分区字段不能是表中已经存在的数据,可以将分区字段看作表的伪列。
增加分区
删除单个分区

hive (default)> alter table dept_partition drop partition (day='20200406'); 

同时删除多个分区

hive (default)> alter table dept_partition add partition(day='20200405') partition(day='20200406');

删除分区
删除单个分区

hive (default)> alter table dept_partition drop partition (day='20200406'); 

同时删除多个分区

hive (default)> alter table dept_partition drop partition (day='20200404'), partition(day='20200405'); 

查看分区表有多少分区

hive> show partitions dept_partition; 

查看分区表结构

hive> desc formatted dept_partition; 

Partition Information

col_name data_type comment

month string
把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式
(1)方式一:上传数据后修复

hive (default)> dfs -mkdir -p 
/user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=13; 
hive (default)> dfs -put /opt/module/datas/dept_20200401.log 
/user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=13;

执行修复命令

hive> msck repair table dept_partition2; 

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

hive (default)> dfs -mkdir -p 
/user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=14; 
hive (default)> dfs -put /opt/module/hive/datas/dept_20200401.log 
/user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=14;

执行添加分区

hive (default)> alter table dept_partition2 add partition(day='201709',hour='14'); 

(3)方式三:创建文件夹后 load 数据到分区
创建目录

hive (default)> dfs -mkdir -p 
/user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=15; 

上传数据

hive (default)> load data local inpath 
'/opt/module/hive/datas/dept_20200401.log' into table 
dept_partition2 partition(day='20200401',hour='15'); 

动态分区调整
关系型数据库中,对分区表 Insert 数据时候,数据库自动会根据分区字段的值,将数据
插入到相应的分区中,Hive 中也提供了类似的机制,即动态分区(Dynamic Partition),只不过, 使用 Hive 的动态分区,需要进行相应的配置。
1)开启动态分区参数设置
(1)开启动态分区功能(默认 true,开启)

hive.exec.dynamic.partition=true 

(2)设置为非严格模式(动态分区的模式,默认 strict,表示必须指定至少一个分区为
静态分区,nonstrict 模式表示允许所有的分区字段都可以使用动态分区。)

hive.exec.dynamic.partition.mode=nonstrict

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

hive.exec.max.dynamic.partitions=1000

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

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

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

hive.exec.max.created.files=100000

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

hive.error.on.empty.partition=false 

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

create table stu_buck(id int, name string) 
clustered by(id) 
into 4 buckets 
row format delimited fields terminated by '\t'; 

查看表结构

hive (default)> desc formatted stu_buck; 
Num Buckets: 4 

导入数据到分桶表中,load 的方式

hive (default)> load data inpath '/student.txt' into table stu_buck;

(5)查看创建的分桶表中是否分成 4 个桶
在这里插入图片描述

分桶规则:
根据结果可知:Hive 的分桶采用对分桶字段的值进行哈希,然后除以桶的个数求余的方
式决定该条记录存放在哪个桶当中
分桶表操作需要注意的事项:
(1)reduce 的个数设置为-1,让 Job 自行决定需要用多少个 reduce 或者将 reduce 的个
数设置为大于等于分桶表的桶数
(2)从 hdfs 中 load 数据到分桶表中,避免本地文件找不到问题
(3)不要使用本地模式

DML
基本插入数据

hive (default)> insert into table student_par 
values(1,'wangwu'),(2,'zhaoliu'); 

基本模式插入(根据单张表查询结果)

hive (default)> insert overwrite table student_par 
select id, name from student where month='201709';

insert into:以追加数据的方式插入到表或分区,原有数据不会删除
insert overwrite:会覆盖表中已存在的数据
注意:insert 不支持插入部分字段
多表(多分区)插入模式(根据多张表查询结果)

hive (default)> from student 
insert overwrite table student partition(month='201707') 
select id, name where month='201709' 
insert overwrite table student partition(month='201706') 
select id, name where month='201709';

根据查询结果创建表(查询的结果会添加到新创建的表中)

create table if not exists student3 
as select id, name from student;

清除表中数据(Truncate)

hive (default)> truncate table student; 

注意:Truncate 只能删除管理表,不能删除外部表中数据
选择特定列查询

hive (default)> select empno, ename from emp; 

注意:
(1)SQL 语言大小写不敏感。
(2)SQL 可以写在一行或者多行
(3)关键字不能被缩写也不能分行
(4)各子句一般要分行写。
(5)使用缩进提高语句的可读性。
列别名

hive (default)> select ename AS name, deptno dn from emp; 

Limit 语句

hive (default)> select * from emp limit 5;

Where 语句
WHERE 子句紧随 FROM 子句
注意:where 子句中不能使用字段别名。

hive (default)> select * from emp where sal >1000; 

比较运算符(Between/In/ Is Null)

hive (default)> select * from emp where sal between 500 and 1000; 
hive (default)> select * from emp where comm is null; 
hive (default)> select * from emp where sal IN (1500, 5000); 

Like
使用 LIKE 运算选择类似的值
选择条件可以包含字符或数字:
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
(1)查找名字以 A 开头的员工信息

hive (default)> select * from emp where ename LIKE 'A%'; 

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

hive (default)> select * from emp where ename LIKE '_A%'; 

逻辑运算符(And/Or/Not)
在这里插入图片描述

hive (default)> select * from emp where sal>1000 and deptno=30;
hive (default)> select * from emp where sal>1000 or deptno=30; 
hive (default)> select * from emp where deptno not IN(30, 20); 

Group By 语句

hive (default)> select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno; 

Having 语句
having 与 where 不同点
(1)where 后面不能写分组函数,而 having 后面可以使用分组函数。
(2)having 只用于 group by 分组统计语句。

hive (default)> select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000; 

等值 Join

hive (default)> select e.empno, e.ename, d.deptno, d.dname from emp e 
join dept d on e.deptno = d.deptno;

表的别名
(1)使用别名可以简化查询。
(2)使用表名前缀可以提高执行效率

hive (default)> select e.empno, e.ename, d.deptno from emp e join dept d 
on e.deptno = d.deptno; 

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

hive (default)> select e.empno, e.ename, d.deptno from emp e join dept d 
on e.deptno = d.deptno;

左外连接
左外连接:JOIN 操作符左边表中符合 WHERE 子句的所有记录将会被返回。

hive (default)> select e.empno, e.ename, d.deptno from emp e left join 
dept d on e.deptno = d.deptno; 

右外连接
右外连接:JOIN 操作符右边表中符合 WHERE 子句的所有记录将会被返回。

hive (default)> select e.empno, e.ename, d.deptno from emp e right join 
dept d on e.deptno = d.deptno; 

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

hive (default)> select e.empno, e.ename, d.deptno from emp e full join 
dept d on e.deptno = d.deptno; 

多表连接
注意:连接 n 个表,至少需要 n-1 个连接条件。例如:连接三个表,至少需要两个连接
条件。

hive (default)>SELECT e.ename, d.dname, l.loc_name 
FROM emp e 
JOIN dept d 
ON d.deptno = e.deptno 
JOIN location l 
ON d.loc = l.loc; 

大多数情况下,Hive 会对每对 JOIN 连接对象启动一个 MapReduce 任务。本例中会首先
启动一个 MapReduce job 对表 e 和表 d 进行连接操作,然后会再启动一个 MapReduce job 将
第一个 MapReduce job 的输出和表 l;进行连接操作。
注意:为什么不是表 d 和表 l 先进行连接操作呢?这是因为 Hive 总是按照从左到右的
顺序执行的。
优化:当对 3 个或者更多表进行 join 连接时,如果每个 on 子句都使用相同的连接键的
话,那么只会产生一个 MapReduce job。
笛卡尔积
笛卡尔集会在下面条件下产生
(1)省略连接条件
(2)连接条件无效
(3)所有表中的所有行互相连接

hive (default)> select empno, dnamefrom emp, dept;

全局排序(Order By)
Order By:全局排序,只有一个 Reducer
ASC(ascend): 升序(默认)
DESC(descend): 降序

hive (default)> select ename, deptno, sal from emp order by deptno, sal;

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

hive (default)> set mapreduce.job.reduces=3; 
hive (default)> select * from emp sort by deptno desc; 

分区(Distribute By)
Distribute By:
在有些情况下,我们需要控制某个特定行应该到哪个 reducer,通常是为
了进行后续的聚集操作。distribute by 子句可以做这件事。distribute by 类似 MR 中 partition
(自定义分区),进行分区,结合 sort by 使用。
对于 distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到 distribute
by 的效果。

hive (default)> set mapreduce.job.reduces=3; 
hive (default)> insert overwrite local directory 
'/opt/module/data/distribute-result' select * from emp distribute by 
deptno sort by empno desc;

注意:
➢ distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后,
余数相同的分到一个区。
➢ Hive 要求 DISTRIBUTE BY 语句要写在 SORT BY 语句之前。
Cluster By
当 distribute by 和 sorts by 字段相同时,可以使用 cluster by 方式。
cluster by 除了具有 distribute by 的功能外还兼具 sort by 的功能。但是排序只能是升序
排序,不能指定排序规则为 ASC 或者 DESC。
以下两种写法等价
hive (default)> select * from emp cluster by deptno;
hive (default)> select * from emp distribute by deptno sort by deptno;
注意:按照部门编号分区,不一定就是固定死的数值,可以是 20 号和 30 号部门分到一
个分区里面去

查询分区表中数据

select * from dept_partition where day='20200401'; 

动态分区插入数据

set hive.exec.dynamic.partition.mode = nonstrict; 
hive (default)> insert into table dept_partition_dy partition(loc) select 
deptno, dname, loc from dept; 

抽样查询
对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结
果。Hive 可以通过对表进行抽样来满足这个需求。
语法: TABLESAMPLE(BUCKET x OUT OF y)

hive (default)> select * from stu_buck tablesample(bucket 1 out of 4 on 

id);

函数

查看系统自带的函数

hive> show functions;

显示自带的函数的用法

hive> desc function upper; 

详细显示自带的函数的用法

hive> desc function extended upper; 

常用内置函数
空字段赋值
函数说明
NVL:给值为 NULL 的数据赋值,它的格式是 NVL( value,default_value)。它的功能是如
果 value 为 NULL,则 NVL 函数返回 default_value 的值,否则返回 value 的值,如果两个参数
都为 NULL ,则返回 NULL。
查询:如果员工的 comm 为 NULL,则用-1 代替

hive (default)> select comm,nvl(comm, -1) from emp; 

如果员工的 comm 为 NULL,则用领导 id 代替

hive (default)> select comm, nvl(comm,mgr) from emp;
CASE WHEN THEN ELSE END 

按需求查询数据

select 
dept_id, 
sum(case sex when '男' then 1 else 0 end) male_count, 
sum(case sex when '女' then 1 else 0 end) female_count 
from emp_sex 
group by dept_id; 

行转列
相关函数说明
CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字
符串;
CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参
数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将
为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接
的字符串之间;
注意: CONCAT_WS must be "string or array
COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重
汇总,产生 Array 类型字段。

SELECT 
t1.c_b, 
CONCAT_WS("|",collect_set(t1.name)) 
FROM ( 
SELECT 
NAME, 
CONCAT_WS(',',constellation,blood_type) c_b 
FROM person_info 
)t1 
GROUP BY t1.c_b 

列转行
函数说明
EXPLODE(col):将 hive 一列中复杂的 Array 或者 Map 结构拆分成多行。
LATERAL VIEW
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和 split, explode 等 UDTF 一起使用,它能够将一列数据拆成多行数据,在此
基础上可以对拆分后的数据进行聚合。

SELECT 
movie, 
category_name 
FROM 
movie_info 
lateral VIEW 
explode(split(category,",")) movie_info_tmp AS category_name; 
窗口函数(开窗函数)
OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变
LAG(col,n,default_val):往前第 n 行数据 
LEAD(col,n, default_val):往后第 n 行数据
select name,orderdate,cost, 
sum(cost) over() as sample1,--所有行相加 
sum(cost) over(partition by name) as sample2,--按 name 分组,组内数据相加 
sum(cost) over(partition by name order by orderdate) as sample3,--按 name 
分组,组内数据累加 
sum(cost) over(partition by name order by orderdate rows between 
UNBOUNDED PRECEDING and current row ) as sample4 ,--和 sample3 一样,由起点到 
当前行的聚合 
sum(cost) over(partition by name order by orderdate rows between 1 
PRECEDING and current row) as sample5, --当前行和前面一行做聚合 
sum(cost) over(partition by name order by orderdate rows between 1 
PRECEDING AND 1 FOLLOWING ) as sample6,--当前行和前边一行及后面一行 
sum(cost) over(partition by name order by orderdate rows between current 
row and UNBOUNDED FOLLOWING ) as sample7 --当前行及后面所有行 
from business; 
rows 必须跟在 order by 子句之后,对排序的结果进行限制,使用固定的行数来限制分 
区中的数据行数量
Rank
RANK() 排序相同时会重复,总数不会变
DENSE_RANK() 排序相同时会重复,总数会减少
ROW_NUMBER() 会根据顺序计算
select name, 
subject, 
score, 
rank() over(partition by subject order by score desc) rp, 
dense_rank() over(partition by subject order by score desc) drp, 
row_number() over(partition by subject order by score desc) rmp 
from score; 
name subject score rp drp rmp 
孙悟空 数学 95 1 1 1 
宋宋 数学 86 2 2 2 
婷婷 数学 85 3 3 3 
大海 数学 56 4 4 4

宋宋 英语 84 1 1 1 
大海 英语 84 1 1 2 
婷婷 英语 78 3 2 3 
孙悟空 英语 68 4 3 4 
大海 语文 94 1 1 1 
孙悟空 语文 87 2 2 2 
婷婷 语文 65 3 3 3 
宋宋 语文 64 4 4 4
Hive自定义函数

用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function)
一进一出
(2)UDAF(User-Defined Aggregation Function)
聚集函数,多进一出
类似于:count/max/min
(3)UDTF(User-Defined Table-Generating Functions)
一进多出
如 lateral view explode()
编程步骤:
(1)继承 Hive 提供的类

org.apache.hadoop.hive.ql.exec.UDF
org.apache.hadoop.hive.ql.udf.generic.GenericUDF 
org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;

(2)实现类中的抽象方法
(3)在 hive 的命令行窗口创建函数
添加 jar

add jar linux_jar_path

创建 function

create [temporary] function [dbname.]function_name AS class_name; 

在 hive 的命令行窗口删除函数

drop [temporary] function [if exists] [dbname.]function_name;

流程添加案例
1.新建maven工程,添加如下依赖

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>3.1.2</version>
</dependency>

如添加判断是否为空自定义函数,代码如下:

package com.bigdata.hive.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.regex.Pattern;
/**
 * 自定义UDF函数
 * 输入:Tom
 * 输出:hello:Tom
 */
@Description(
        name = "udf_is_null",
        value = "_FUNC_(str) - Returns str is null?0:1",
        extended = "Example:\n  > SELECT _FUNC_(\'Facebook\') FROM src LIMIT 1;\n   return    1 "
)
public class UdfIsNull extends UDF {
    public int evaluate(final String s) {
        if (s == null  || s.toString().trim().toLowerCase().equals("null") || Pattern.matches("\\s+",s.toString())||s.toString().trim().equals("")) {
            return 0;
        }
        return 1;
    }
    public static void main(String[] args) {
        System.out.println("值为"+new UdfIsNull().evaluate(new String("null"  )));
    }
}

方式一:添加临时函数(仅当前会话有效)

a将jar上传至服务器,进入hive,执行: add jar /root/jar/hive_function-1.0-SNAPSHOT.jar;

在这里插入图片描述

b.执行命令,添加临时函数:create temporary function udf_is_null as 'com.bigdata.hive.udf.UdfIsNull';

在这里插入图片描述

c.查看函数 desc function udf_is_null;

在这里插入图片描述

d.测试函数: select udf_is_null(“”);

在这里插入图片描述

方式二:添加永久函数(永久函数,创建后可以在任意客户端使用)

a.将jar上传至hdfs文件系统:hdfs dfs -put ./hive_function-1.0-SNAPSHOT.jar /libs

在这里插入图片描述


```sql
b.进入hive,创建函数
create function udf_is_null
as 'com.bigdata.hive.udf.UdfIsNull'
using jar 'hdfs:///libs/hive_function-1.0-SNAPSHOT.jar'

在这里插入图片描述

Hive性能调优
文件存储格式:
Hive 支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、rc、ORC、PARQUET。
第一种:TextFile
1、存储方式:行存储。默认格式,如果建表时不指定默认为此格式。
2、每一行都是一条记录,每行都以换行符"\n"结尾。默认是不压缩,但可以采用多种压缩方式,但是部分压缩算法压缩数据后生成的文件是不支持split。
3、可结合Gzip、Bzip2等压缩方式一起使用(系统会自动检查,查询时会自动解压),推荐选用可切分的压
缩算法。
4、该类型的格式可以识别在hdfs上的普通文件格式(如txt、csv),因此该模式常用语仓库数据接入和导出层;
5、无法区分数据类型,各个字段都被认为是文本,但需要制定列分隔符和行分隔符。
第二种:Sequence File
1、SequenceFile是一种二进制文件,以<key,value>的形式序列化到文件中。存储方式:行存储;
2、支持三种压缩选择:NONE、RECORD、BLOCK。RECORD压缩率低,一般建议使用BLOCK压缩。
3、优势是文件和Hadoop API的MapFile是相互兼容的
4、缺点是由于该种模式是在textfile基础上加了些其他信息,故该类格式的大小要大于textfile,现阶段基本上不用。
第三种:RC File
1、存储方式:数据按行分块,每块按照列存储 。
A、首先,将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。
B、其次,块数据列式存储,有利于数据压缩和快速的列存取。
2、相对来说,RCFile对于提升任务执行性能提升不大,但是能节省一些存储空间。可以使用升级版的ORC格
式。
第四种:ORC File
1、存储方式:数据按行分块,每块按照列存储
2、Hive提供的新格式,属于RCFile的升级版,性能有大幅度提升,而且数据可以压缩存储,压缩快,快速
列存取。
3、ORC File会基于列创建索引,当查询的时候会很快,现阶段主要使用的文件格式
第五种:Parquet File
1、存储方式:列式存储。
2、Parquet对于大型查询的类型是高效的。对于扫描特定表格中的特定列查询,Parquet特别有用。
Parquet一般使用Snappy、Gzip压缩,默认是Snappy
Sql调优
调优方式:explain querySQL 查看sql执行计划
1.空值倾斜 – 过滤空值,降低空值关联引起的数据倾斜
2.减少处理数据量(谓词下推)

使用分区剪裁、列剪裁

select a.*
from a
left join b on a.uid = b.uid
where a.dt=2022-08-10and b.dt=2022-08-10

on的条件没有过滤null值的情况,如果两个数据表存在大批量null值的情况,会造成数据倾斜。

select a.*
from a
left join b on (b.uid is not null and a.uid = b.uid and b.dt=2022-08-10)
where a.dt=2022-08-10

– 强调必须手动谓词下推

selectselect a. from a where a.dt=2022-08-10)a
left joinselect b.* from a where a.dt=2022-08-10and b.uid is not null)b
on a.uid = b.uid

3.少用COUNT DISTINCT

因为COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换,虽然会多用一个Job来完成,但在数据量大的情况下,这个绝对是值得的。

select count(distinct uid)
from test
where dt=2022-08-10and uid is not null
转换为:
select count(a.uid)
from
(select uid
from test
where uid is not null and dt =2022-08-10group by uid
) a

4.使用with as
拖慢Hive查询效率除了join产生的shuffle以外,还有一个就是子查询,在SQL语句里面尽量减少子查询。with as是将语句中用到的子查询事先提取出来(类似临时表),使整个查询当中的所有模块都可以调用该查询结果。使用with as可以避免Hive对不同部分的相同子查询进行重复计算。
其最大的好处就是适当的提高代码可读性,而且如果with子句在后面要多次使用到,这可以大大的简化SQL;更重要的是:一次分析,多次使用,这也是为什么会提供性能的地方,达到了“少读”的目标。

with test1 as
(
select uid
from b
where dt =2022-08-10and uid is not null
)
select a.*
from a
left join test1 on a.uid = test1.uid
where a.dt=2022-08-10and a.uid is not null

5.使用mapjoin广播小表

适用于小表JOIN大表的场景,由于表的JOIN操作是在Map端且在内存进行的,所以其并不需要启动Reduce任务也就不需要经过shuffle阶段,从而能在一定程度上节省资源提高JOIN效率
方法一:显示使用

SELECT /+ MAPJOIN(smalltable)/ .key,value
FROM smalltable JOIN bigtable ON smalltable.key = bigtable.key

方法二:配置参数

set hive.auto.convert.join = true;

– 默认值为true,自动开户MAPJOIN优化

set hive.mapjoin.smalltable.filesize=25000000;

–默认值为2500000(25M),通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中
数据量预估
使用join前统计下双方的数据量级,预估计算量,根据数据量进行优化

6.sort by代替order by
HiveQL中的order by与其他SQL方言中的功能一样,就是将结果按某字段全局排序,这会导致所有map端数据都进入一个reducer中,在数据量大时可能会长时间计算不完。如果使用sort by,那么还是会视情况启动多个reducer进行排序,并且保证每个reducer内局部有序。

distribute by column sort by column asc|desc

配置调优

set hive.exec.parallel=true; //打开任务并行执行
hive.fetch.task.conversion=more 默认是 more,老版本hive默认是 minimal,该属性修改为 more 以后,在全局查找、字段查找、limit 查找等都不走 mapreduce。
set hive.exec.mode.local.auto=true; //开启本地 mr 
//设置 local mr 的最大输入数据量,当输入数据量小于这个值时采用 local mr 的方式,默认 134217728,即 128M 
set hive.exec.mode.local.auto.inputbytes.max=50000000; 
//设置 local mr 的最大输入文件个数,当输入文件个数小于这个值时采用 local mr 的方式,默 
认为 4 
set hive.exec.mode.local.auto.input.files.max=10;
set hive.auto.convert.join = true; 默认为 true 设置自动选择 Mapjoin
set hive.mapjoin.smalltable.filesize = 25000000; 大表小表的阈值设置(默认 25M 以下认为是小表): 






Map-Side聚合
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。
set hive.map.aggr=true; 开启在Map端的聚合
hive.groupby.mapaggr.checkinterval:map端group by执行聚合时处理的多少行数据(默认:100000)
hive.map.aggr.hash.min.reduction:进行聚合的最小比例(预先对100000条数据做聚合,若聚合之后的数据量/100000的值大于该配置0.5,则不会聚合
hive.map.aggr.hash.percentmemory:map端聚合使用的内存的最大值
hive.map.aggr.hash.force.flush.memory.threshold:map端做聚合操作是hash表的最大可用内容,大于该值则会触发flush
hive.groupby.skewindata是否对GroupBy产生的数据倾斜做优化,默认为false(自动优化解决思路如下):
Map端两个MapReduce,第一个Mapreduce随机来分发数据。
然后另一个Mapreduce根据此Mapreduce的结果在到Reduce的机器上去拉取数据。
Map数量相关的参数
mapred.max.split.size  一个split的最大值,即每个map处理文件的最大值
mapred.min.split.size.per.node 一个节点上split的最小值
mapred.min.split.size.per.rack 一个机架上split的最小值
Reduce数量相关的参数
mapred.reduce.tasks 强制指定reduce任务的数量
hive.exec.reducers.bytes.per.reducer 每个reduce任务处理的数据量
hive.exec.reducers.max 每个任务最大的reduce数
set mapred.task.timeout=600000000;  设置超时时间
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值