0301-Hive
- 第一章 Hive基本概念
- 第二章 HIve安装
- 2.1 Hive 安装部署
- 2.2 MySQL安装
- 2.3 Hive 元数据配置到MySQL
- 2.4 Hive JDBC访问
- 2.5 Hive 常用交互命令
- 2.6 Hive 其他命令操作
- 2.7 Hive 常见属性配置
- 第三章 Hive数据类型
- 第四章 DDL数据定义语言
- 第五章 DML数据操作语言
- 5.1 数据导入
- 5.1.1 向表中装载数据(load)
- 5.1.2 通过查询语句向表中插入数据(insert...select)
- 5.1.3 查询语句中创建表并加载数据(create... as select)
- 5.1.4 创建表是通过Location指定加载数据路径
- 5.1.5 Import数据到指定Hive表中
- 5.2 数据导出
- 第六章 数据查询
- 6.1 基本查询
- 6.2 Where语句
- 6.3 分组
- 6.4 Join语句
- 6.5 排序
- 6.5.1 全局排序(Order By)`慎用`
- 6.5.2 每个Reducer内部排序(Sort By)
- 6.5.3 分区排序(Distribute By + Sort By)
- 6.5.4 Cluster By
- 6.6 分桶及抽样查询
- 6.7 其他常见查询函数
- 第七章 函数
- 第八章 压缩与存储
- 第九章 企业级优化
- 第十章 Hive实战
第一章 Hive基本概念
1.1 什么是Hive
Hive是由FaceBook开源用于解决海量结构化日志的数据统计
Hive是基于Hadoop的一个数据仓库工具, 可以将结构化的数据文件映射为一张二维表 ,并提供类SQL查询功能.
Hive的本质是,将HQL转化成MapReduce程序
- Hive处理的数据存储在HDFS
- Hive分析数据底层的实现时MapReduce
- 执行程序运行在YARN上
1.2 Hive的优缺点
1.2.1 优点
- 操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)。
- 避免了去写MapReduce,减少开发人员的学习成本。
- Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合。
- Hive优势在于处理大数据,对于处理小数据没有优势,因为Hive的执行延迟比较高。
- Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
1.2.2 缺点
- Hive的HQL表达能力有限
(1)迭代式算法无法表达
(2)数据挖掘方面不擅长,由于MapReduce数据处理流程的限制,效率更高的算法却无法实现。- Hive的效率比较低
(1)Hive自动生成的MapReduce作业,通常情况下不够智能化
(2)Hive调优比较困难,粒度较粗
1.3 Hive的架构原理
- 用户接口:Client
CLI(command-line interface)、JDBC/ODBC(jdbc访问hive)、WEBUI(浏览器访问hive)
- 元数据:Metastore
元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;
- Hadoop
使用HDFS进行存储,使用MapReduce进行计算。
- 驱动器: 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中执行,最后,将执行返回的结果输出到用户交互接口。
1.4 Hive和数据库的比较
数据库: 为业务系统提供交互式访问
数据仓库: 用作对过去的数据进行历史分析
从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处
1.4.1 查询语言
由于SQL被广泛的应用在数据仓库中,因此,专门针对Hive的特性设计了类SQL的查询语言HQL。熟悉SQL开发的开发者可以很方便的使用Hive进行开发。
1.4.2 数据存储位置
Hive 是建立在 Hadoop 之上的,所有 Hive 的数据都是存储在 HDFS 中的。而数据库则可以将数据保存在块设备或者本地文件系统中。
1.4.3 数据更新
由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不建议对数据的改写,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用 INSERT INTO … VALUES 添加数据,使用 UPDATE … SET修改数据。
1.4.4 执行
Hive中大多数查询的执行是通过 Hadoop 提供的 MapReduce 来实现的。而数据库通常有自己的执行引擎。
1.4.5 执行延迟
Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致 Hive 执行延迟高的因素是 MapReduce框架。由于MapReduce 本身具有较高的延迟,因此在利用MapReduce 执行Hive查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
1.4.6 可扩展性
由于Hive是建立在Hadoop之上的,因此Hive的可扩展性是和Hadoop的可扩展性是一致的(世界上最大的Hadoop 集群在 Yahoo!,2009年的规模在4000 台节点左右)。而数据库由于 ACID 语义的严格限制,扩展行非常有限。目前最先进的并行数据库 Oracle 在理论上的扩展能力也只有100台左右。
1.4.7 数据规模
由于Hive建立在集群上并可以利用MapReduce进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。
第二章 HIve安装
2.1 Hive 安装部署
- Hive安装及配置
(1) 把apache-hive-1.2.1-bin.tar.gz上传到linux的/opt/software目录下
(2) 解压apache-hive-1.2.1-bin.tar.gz到/opt/module/目录下面
(3) 修改apache-hive-1.2.1-bin.tar.gz的名称为hive
(4) 修改/opt/module/hive/conf目录下的hive-env.sh.template名称为hive-env.sh
(5) 配置hive-env.sh文件
[yanlzh@node01 software]$ tar -zxvf apache-hive-1.2.1-bin.tar.gz -C /opt/module/
[yanlzh@node01 module]$ mv apache-hive-1.2.1-bin/ hive
[yanlzh@node01 conf]$ mv hive-env.sh.template hive-env.sh
[yanlzh@node01 conf]$ vi hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-2.7.2
export HIVE_CONF_DIR=/opt/module/hive/conf
2.2 MySQL安装
2.2.1 安装包准备
(D:\software\mysql-libs.zip)
- 查看mysql是否安装, 如果安装了, 卸载mysql
[root@node01 ~]# rpm -qa|grep mysql
mysql-libs-5.1.73-7.el6.x86_64
[root@node01 ~]# rpm -e --nodeps mysql-libs-5.1.73-7.el6.x86_64
- 解压mysql-libs.zip文件到当前目录
[root@node01 software]# unzip mysql-libs.zip
[root@node01 software]# ls
mysql-libs.zip
mysql-libs
- 进入mysql-libs文件夹下
[root@node01 mysql-libs]# ll
总用量 76048
-rw-r--r--. 1 root root 18509960 3月 26 2015 MySQL-client-5.6.24-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 3575135 12月 1 2013 mysql-connector-java-5.1.27.tar.gz
-rw-r--r--. 1 root root 55782196 3月 26 2015 MySQL-server-5.6.24-1.el6.x86_64.rpm
2.2.2 安装MySQL服务器
- 安装mysql服务器
[root@node01 mysql-libs]# rpm -ivh MySQL-server-5.6.24-1.el6.x86_64.rpm
- 查看产生的随机密码
[root@node01 mysql-libs]# cat /root/.mysql_secret
OEXaQuS8IWkG19Xs
- 查看mysql状态
[root@node01 mysql-libs]# service mysql status
- 启动mysql
[root@node01 mysql-libs]# service mysql start
2.2.3 安装MySQL客户端
- 安装mysql客户端
[root@node01 mysql-libs]# rpm -ivh MySQL-client-5.6.24-1.el6.x86_64.rpm
- 链接mysql
[root@node01 mysql-libs]# mysql -uroot -p_uJSYNxbFK6QsqSu
- 修改密码
mysql> SET PASSWORD=PASSWORD('000000');
- 退出mysql
mysql> exit
2.2.4 MySQL中user表中主机配置
1.进入mysql
[root@node01 mysql-libs]# mysql -uroot -p000000
2.显示数据库
mysql> show databases;
3.使用mysql数据库
mysql> use mysql;
4.展示mysql数据库中的所有表
mysql> show tables;
5.展示user表的结构
mysql> desc user;
6.查询user表
mysql> select User, Host, Password from user;
7.修改user表,把Host表内容修改为%
mysql> update user set host='%' where host='localhost';
8.删除root用户的其他host
mysql> delete from user where Host='hadoop102';
mysql> delete from user where Host='127.0.0.1';
mysql> delete from user where Host='::1';
9.刷新
mysql> flush privileges;
10.退出
mysql> quit;
2.3 Hive 元数据配置到MySQL
2.3.1 拷贝驱动
D:\software\06_hive\mysql-connector-java-5.1.40-bin.jar
1.在/opt/software/mysql-libs目录下解压mysql-connector-java-5.1.27.tar.gz驱动包
[root@node01 mysql-libs]# tar -zxvf mysql-connector-java-5.1.27.tar.gz
2.拷贝/opt/software/mysql-libs/mysql-connector-java-5.1.27目录下的mysql-connector-java-5.1.27-bin.jar到/opt/module/hive/lib/
[root@node01 mysql-connector-java-5.1.27]# cp mysql-connector-java-5.1.27-bin.jar
/opt/module/hive/lib/
2.3.2 配置Metastore到MySQL
1.在/opt/module/hive/conf目录下创建一个hive-site.xml
[yanlzh@node01 conf]$ touch hive-site.xml
[yanlzh@node01 conf]$ vi hive-site.xml
2.根据官方文档配置参数,拷贝数据到hive-site.xml文件中
https://cwiki.apache.org/confluence/display/Hive/AdminManual+MetastoreAdmin
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node11:3306/metastore?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>1229</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
</configuration>
2.3.3 Hive 执行引擎Tez
- 将apache-tez-0.9.1-bin.tar.gz 解压到/opt/module/ 下
- 进入到/opt/module/hive/conf, 修改hive-env.sh, 添加如下配置
export TEZ_HOME=/opt/module/tez-0.9.1 #是你的tez的解压目录
export TEZ_JARS=""
for jar in `ls $TEZ_HOME |grep jar`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/$jar
done
for jar in `ls $TEZ_HOME/lib`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/lib/$jar
done
export HIVE_AUX_JARS_PATH=/opt/module/hadoop-2.7.2/share/hadoop/common/hadoop-lzo-0.4.20.jar$TEZ_JARS
- 在 /opt/module/hive/conf 下面创建一个tez-site.xml文件. 添加如下内容
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>tez.lib.uris</name>
<value>${fs.defaultFS}/tez/tez-0.9.1,${fs.defaultFS}/tez/tez-0.9.1/lib</value>
</property>
<property>
<name>tez.lib.uris.classpath</name>
<value>${fs.defaultFS}/tez/tez-0.9.1,${fs.defaultFS}/tez/tez-0.9.1/lib</value>
</property>
<property>
<name>tez.use.cluster.hadoop-libs</name>
<value>true</value>
</property>
<property>
<name>tez.history.logging.service.class</name>
<value>org.apache.tez.dag.history.logging.ats.ATSHistoryLoggingService</value>
</property>
</configuration>
- 在hive-site.xml文件中添加如下配置
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
- 将/opt/module/tez-0.9.1 上传到HDFS的/tez路径
- 运行Tez时检查到用过多内存而被NodeManager杀死进程问题:
解决方案: 关掉虚拟内存检查。修改yarn-site.xml
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
2.4 Hive JDBC访问
- 启动hiveserver2 服务
[yanlzh@node01 hive]$ bin/hiveserver2
- 启动beeline
[yanlzh@node01 hive]$ bin/beeline
Beeline version 1.2.1 by Apache Hive
beeline>
- 连接hiveserver2
连接出错的问题
beeline> !connect jdbc:hive2://node01:10000(回车)
Connecting to jdbc:hive2://node01:10000
Enter username for jdbc:hive2://node01:10000: atguigu(回车)
Enter password for jdbc:hive2://node01:10000: (直接回车)
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://node01:10000> show databases;
+----------------+--+
| database_name |
+----------------+--+
| default |
| hive_db2 |
+----------------+--+
2.5 Hive 常用交互命令
1.“-e”不进入hive的交互窗口执行sql语句
[yanlzh@node01 hive]$ bin/hive -e "select id from student;"
2.“-f”执行脚本中sql语句
(1)在/opt/module/datas目录下创建hivef.sql文件
[yanlzh@node01 datas]$ touch hivef.sql
文件中写入正确的sql语句
select *from student;
(2)执行文件中的sql语句
[yanlzh@node01 hive]$ bin/hive -f /opt/module/datas/hivef.sql
(3)执行文件中的sql语句并将结果写入文件中
[yanlzh@node01 hive]$ bin/hive -f /opt/module/datas/hivef.sql > /opt/module/datas/hive_result.txt
2.6 Hive 其他命令操作
1.退出hive窗口:
hive(default)>exit;
hive(default)>quit;
在新版的hive中没区别了,在以前的版本是有的:
exit:先隐性提交数据,再退出;
quit:不提交数据,退出;
2.在hive cli命令窗口中如何查看hdfs文件系统
hive(default)>dfs -ls /;
3.在hive cli命令窗口中如何查看本地文件系统
hive(default)>! ls /opt/module/datas;
4.查看在hive中输入的所有历史命令
(1)进入到当前用户的根目录/root或/home/yanlzh
(2)查看. hivehistory文件
[yanlzh@node01 ~]$ cat .hivehistory
2.7 Hive 常见属性配置
2.7.1 Hive 数据仓库位置配置
- Default数据仓库的最原始位置是在hdfs上的:/user/hive/warehouse路径下。
- 在仓库目录下,没有对默认的数据库default创建文件夹。如果某张表属于default数据库,直接在数据仓库目录下创建一个文件夹。
- 修改default数据仓库原始位置(将hive-default.xml.template如下配置信息拷贝到hive-site.xml文件中)。
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
2.7.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>
2.7.3 Hive运行日志信息配置
- Hive的log默认存放在/tmp/yanlzh/hive.log目录下(当前用户名下)
- 修改hive的log存放日志到/opt/module/hive/logs
(1)修改/opt/module/hive/conf/hive-log4j.properties.template文件名称为 hive-log4j.properties
[atguigu@hadoop102 conf]$ pwd
/opt/module/hive/conf
[atguigu@hadoop102 conf]$ mv hive-log4j.properties.template hive-log4j.properties
(2)在hive-log4j.properties文件中修改log存放位置
hive.log.dir=/opt/module/hive/logs
2.7.4 参数配置方式
- 查看当前所有配置信息
hive (default)> set;
hive (default)> set mapred.reduce.tasks;
- 参数配置的三种方式
- 配置文件方式
默认配置文件:hive-default.xml
用户自定义配置文件:hive-site.xml
注意:用户自定义配置会覆盖默认配置。另外,Hive也会读入Hadoop的配置,因为Hive是作为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置。配置文件的设定对本机启动的所有Hive进程都有效。- 命令行参数方式
启动Hive时,可以在命令行添加-hiveconf param=value来设定参数。
注意:仅对本次hive启动有效
[yanlzh@node01 hive]$ bin/hive -hiveconf mapred.reduce.tasks=10;
- 参数声明方式
可以在HQL中使用SET关键字设定参数
注意:仅对本次hive启动有效。
hive (default)> set mapred.reduce.tasks=100;
上述三种设定方式的优先级依次递增。即配置文件 < 命令行参数 < 参数声明。
注意某些系统级的参数,例如log4j相关的设定,必须用前两种方式设定,因为那些参数的读取在会话建立以前已经完成了。
总结所有的配置文件
hive-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node11:3306/metastore?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>1229</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
</configuration>
hive-env.sh
# Set HADOOP_HOME to point to a specific hadoop install directory
HADOOP_HOME=/opt/module/hadoop-2.7.2
# Hive Configuration Directory can be controlled by:
export HIVE_CONF_DIR=/opt/module/hive/conf
# Folder containing extra ibraries required for hive compilation/execution can be controlled by:
# export HIVE_AUX_JARS_PATH=
export TEZ_HOME=/opt/module/tez-0.9.1 #是你的tez的解压目录
export TEZ_JARS=""
for jar in `ls $TEZ_HOME |grep jar`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/$jar
done
for jar in `ls $TEZ_HOME/lib`; do
export TEZ_JARS=$TEZ_JARS:$TEZ_HOME/lib/$jar
done
export HIVE_AUX_JARS_PATH=/opt/module/hadoop-2.7.2/share/hadoop/common/hadoop-lzo-0.4.20.jar$TEZ_JARS
tez-sit.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>tez.lib.uris</name>
<value>${fs.defaultFS}/tez/tez-0.9.1,${fs.defaultFS}/tez/tez-0.9.1/lib</value>
</property>
<property>
<name>tez.lib.uris.classpath</name>
<value>${fs.defaultFS}/tez/tez-0.9.1,${fs.defaultFS}/tez/tez-0.9.1/lib</value>
</property>
<property>
<name>tez.use.cluster.hadoop-libs</name>
<value>true</value>
</property>
<property>
<name>tez.history.logging.service.class</name>
<value>org.apache.tez.dag.history.logging.ats.ATSHistoryLoggingService</value>
</property>
</configuration>
注意: 初始化元数据库(2.x以后) ./schematool -initSchema -dbType mysql
第三章 Hive数据类型
3.1 基本数据类型
对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。
3.2 集合数据类型
数据类型 | 描述 | 语法实例 |
---|---|---|
STRUCT | 和c语言中的struct类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING, last STRING},那么第1个元素可以通过字段.first来引用。 | 例如struct<street:string, city:string> |
MAP | MAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数据类型是MAP,其中键->值对是’first’->’John’和’last’->’Doe’,那么可以通过字段名[‘last’]获取最后一个元素 | 例如map<string, int> |
ARRAY | 数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,编号从零开始。例如,数组值为[‘John’, ‘Doe’],那么第2个元素可以通过数组名[1]进行引用。 | 例如array< string> |
案例
- 本地数据
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
- 创建表
yangyang,
caicai _ susu,
xiao yang : 18 _ xiaoxiao yang : 19,
chao yang _ beijing
create table person
(
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, STRUCT, ARRAY的分隔符
map keys terminated by ':' -- MAP中key value的分隔符
lines terminated by '\n' -- 行分隔符
3.3 类型转化
第四章 DDL数据定义语言
4.1 创建数据库
CREATE DATABASE [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, …)];
- 创建一个数据库, 数据库在HDFS上的默认存储路径是 /user/hive/warehouse/*.db。
hive (default)> create database db_hive;
OK
Time taken: 0.102 seconds
- 避免要创建的数据库已经存在错误,增加if not exists判断。(标准写法)
hive (default)> create database if not exists db_hive;
OK
Time taken: 0.038 seconds
- 创建一个数据库,指定数据库在HDFS上存放的位置
hive (default)> create database db_hive2 location '/db_hive2.db';
OK
Time taken: 0.042 seconds
4.2 查询数据库
- 显示数据库
hive (default)> show databases;
OK
database_name
db_hive
db_hive2
default
Time taken: 0.026 seconds, Fetched: 3 row(s)
- 过滤显示查询的数据库
hive (default)> show databases like 'db_hive*';
OK
database_name
db_hive
db_hive2
Time taken: 0.027 seconds, Fetched: 2 row(s)
- 显示数据库信息
hive (default)> desc database db_hive;
OK
db_name comment location owner_name owner_type parameters
db_hive hdfs://node11:9000/user/hive/warehouse/db_hive.db yanlzh USER
Time taken: 0.048 seconds, Fetched: 1 row(s)
- 显示数据库详细信息
hive (default)> desc database extended db_hive;
OK
db_name comment location owner_name owner_type parameters
db_hive hdfs://node11:9000/user/hive/warehouse/db_hive.db yanlzh USER
Time taken: 0.038 seconds, Fetched: 1 row(s)
- 切换当前数据库
hive (default)> use db_hive;
OK
Time taken: 0.024 seconds
hive (db_hive)>
4.3 修改数据库
用户可以使用ALTER DATABASE命令为某个数据库的DBPROPERTIES设置键-值对属性值,来描述这个数据库的属性信息。数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置。
hive (db_hive)> alter database db_hive set dbproperties('createtime'='2019-12-05');
OK
Time taken: 0.066 seconds
hive (db_hive)> desc database extended db_hive;
OK
db_name comment location owner_name owner_type parameters
db_hive hdfs://node11:9000/user/hive/warehouse/db_hive.db yanlzh USER {createtime=2019-12-05}
Time taken: 0.047 seconds, Fetched: 1 row(s)
4.4 删除数据库
- 删除空数据库
hive (default)> drop database db_hive2;
OK
Time taken: 0.334 seconds
- 如果数据库不为空, 可以采用cascade命令, 强制删除
hive> drop database db_hive;
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(message:Database db_hive is not empty. One or more tables exist.)
hive> drop database db_hive cascade;
4.5 创建表
建表语法
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]
字段解释说明
- create table
- external
- comment
- partitioned by
- clustered by
- sorted by
不常用,对桶中的一个或多个列另外排序 - row format
- stored as
- location
- as
- like
4.5.1 管理表
- 理论
默认创建的表都是管理表
删除管理表时, 元数据和表中数据一起被删除
管理表不适合和其他工具共享数据
- 案例
(1) 创建普通表
hive (db_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';
OK
Time taken: 1.273 seconds
(2) 根据查询结果创建表(查询结果会添加到新创建的表中)
hive (db_hive)> create table if not exists student2 as select id, name from student;
(3) 根据已经存在的表结构创建表
hive (db_hive)> create table if not exists student3 like student;
OK
Time taken: 0.782 seconds
(4) 查询表结构
hive (db_hive)> desc student3;
OK
col_name data_type comment
id int
name string
Time taken: 0.115 seconds, Fetched: 2 row(s)
4.5.2 外部表
- 理论
删除表不会删除表数据
元数据信息会被删除掉
- 管理表和外部表的使用场景
- 案例
(1) 上传数据到HDFS
[yanlzh@node11 ~]$ hadoop fs -mkdir /txt
[yanlzh@node11 ~]$ hadoop fs -put student.txt /txt/;
(2) 创建外部表
hive (db_hive)> create external table stu_external(id int, name string)
> row format delimited fields terminated by '\t'
> location '/txt';
OK
Time taken: 0.165 seconds
hive (db_hive)> select * from stu_external;
OK
stu_external.id stu_external.name
1 zhangsan
2 lisi
3 wangwu
4 liuqi
Time taken: 0.36 seconds, Fetched: 4 row(s)
(3) 删除外部表
hive (db_hive)> drop table stu_external;
外部表删除后,hdfs中的数据还在,但是metadata中stu_external的元数据已被删除
4.5.3 管理表与外部表的相互转换
- 修改内部表student2 为外部表
alter table student2 set tblproperties('EXTERNAL'='TRUE');
- 修改外部表student2 为内部表
alter table student2 set tblproperties('EXTERNAL'='FALSE');
注意:(‘EXTERNAL’=‘TRUE’)和(‘EXTERNAL’=‘FALSE’)为固定写法,区分大小写!
4.6 分区表
分区表实际上就是对应一个HDFS文件系统上的独立的文件夹, 该文件夹下是该分区所有的数据文件, HIve中分区就是分目录, 把 一个大的数据集根据业务需要分割成小的数据集(日志文件按照日期分区, 每天一张日志表) . 在查询的时候通过WHERE子句中表达式选择查询所需要的指定的分区(where dt=‘2019-11-12’), 这样查询效率会提高很多.
4.6.1 分区表基本操作
- 引入分区表(需要根据日期对日志进行管理)
- 创建分区表语法
hive (db_hive)> create table dept_partition(
> deptno int,dname string, loc string
> )
> partitioned by (month string)
> row format delimited fields terminated by '\t';
OK
Time taken: 0.242 seconds
注意:分区字段不能是表中已经存在的数据,可以将分区字段看作表的伪列
- 加载数据到分区表中
load data local inpath '/home/yanlzh/dept-201909.txt' into table dept_partition partition(month='201909');
load data local inpath '/home/yanlzh/dept-201910.txt' into table dept_partition partition(month='201910');
load data local inpath '/home/yanlzh/dept-201911.txt' into table dept_partition partition(month='201911');
- 查询分区表中的数据
hive (db_hive)> select * from dept_partition where month = '201909';
OK
dept_partition.deptno dept_partition.dname dept_partition.loc dept_partition.month
1001 d01 sh 201909
1002 d02 bj 201909
1003 d03 xn 201909
1004 d04 lm 201909
Time taken: 1.541 seconds, Fetched: 4 row(s)
- 增加分区
(1) 创建单个分区
hive (db_hive)> alter table dept_partition add partition(month='201908');
OK
Time taken: 0.673 seconds
(2) 同时创建多个分区(不加逗号)
hive (db_hive)> alter table dept_partition add partition(month='201907') partition(month='201906');
OK
Time taken: 0.231 seconds
- 删除分区
(1) 删除单个分区
hive (db_hive)> alter table dept_partition drop partition(month='201907');
Dropped the partition month=201907
OK
Time taken: 0.5 seconds
(2) 删除多个分区(加逗号)
hive (db_hive)> alter table dept_partition drop partition(month='201906'), partition(month='201908');
Dropped the partition month=201906
Dropped the partition month=201908
OK
Time taken: 0.332 seconds
- 查看分区个数
hive (db_hive)> show partitions dept_partition;
OK
partition
month=201909
month=201910
month=201911
Time taken: 0.177 seconds, Fetched: 3 row(s)
4.6.2 分区表注意事项
- 创建二级分区表
hive (db_hive)> create table dept_partition2(
> deptno int, dname string, loc string
> )
> partitioned by (month string, day string)
> row format delimited fields terminated by '\t';
OK
Time taken: 0.249 seconds
4.7 修改表
4.7.1 重命名表
hive (default)> alter table dept_partition2 rename to dept_part;
4.7.2 增加/修改/替换列信息
- 添加列
hive (default)> alter table dept_partition add columns(deptdesc string);
- 更新列
hive (default)> alter table dept_partition change column deptdesc desc int;
- 替换列
hive (default)> alter table dept_partition replace columns(deptno string, dname string, loc string);
4.8 删除表
hive (default)> drop table dept_partition;
hive (default)> truncate table dept_partition;
第五章 DML数据操作语言
5.1 数据导入
5.1.1 向表中装载数据(load)
- 语法
load data [local] inpath ‘文件路径’ [overwrite] into table student [partition(partcol = val)];
- 案例
5.1.2 通过查询语句向表中插入数据(insert…select)
- 基本模式插入(根据单张表查询结果)
hive (default)> insert into table student partition(month = '201909')
> select id, name from student where month = '201909';
- 多表(多分区)插入(根据多张表查询结果)
from student
insert overwrite table student partition (month = '201909')
select id, name where month = '201909'
insert overwrite table student partition (month = '201908')
select id, name where month = '201908';
5.1.3 查询语句中创建表并加载数据(create… as select)
create table if not exists student3 as select id, name from student;
5.1.4 创建表是通过Location指定加载数据路径
先将数据上传到hdfs上
hive (default)> dfs -mkdir /student;
hive (default)> dfs -put /opt/module/datas/student.txt /student;
create external table if not exists student4(id int ,name string)
row format delimited
fields terminated by '\t'
location '/student';
5.1.5 Import数据到指定Hive表中
hive (default)> import table student2 partition(month='201709') from
'/user/hive/warehouse/export/student';
5.2 数据导出
5.2.1 Insert导出
- 将查询的结果导出到本地
insert overwrite local directory '/opt/module/datas/export/student'
select * from student;
- 将查询的结果格式化导出到本地
insert overwrite local directory '/opt/module/datas/exports/student1'
row format delimited
fields terminated by '\t'
select * from student;
- 将查询的结果导出到HDFS上
insert overwrite directory '/user/yanlzh/student2'
row format delimited
fields terminated by '\t'
select * from student;
5.2.2 Hadoop 命令导出到本地
hive (default)> dfs -get /user/hive/warehouse/student/month=201709/000000_0
/opt/module/datas/export/student3.txt;
5.2.3 Hive Shell命令导出到本地
[yanlzh@node11 hive]$ bin/hive -e 'select * from default.student;' >
/opt/module/datas/export/student4.txt;
5.2.4 Export 导出到HDFS上
hive (default)> export table default.student to '/user/hive/warehouse/export/student';
export和import主要用于两个Hadoop平台集群之间Hive表迁移。
5.2.5 Sqoop 导出
第六章 数据查询
6.1 基本查询
select… from
6.2 Where语句
select… from… where
6.3 分组
group by [having ]
6.4 Join语句
Hive只支持等值Join, 不支持非等值Join
6.5 排序
6.5.1 全局排序(Order By)慎用
Order By: 全局排序, 所以
只有一个Reducer
, 要谨慎使用
同样要慎用的还有distinct
,因为也是只有一个Reducer, 可以使用group by代替
6.5.2 每个Reducer内部排序(Sort By)
对于大规模数据Order by 的效率非常低下, 在很多情况下, 并不需要全局排序, 此时可以使用Sort By
Sort By 为每个reducer产生一个排序文件. 每个reducer内部进行排序, 对全局结果集来说不是排序;
hive (default)> select * from emp sort by deptno desc;
6.5.3 分区排序(Distribute By + Sort By)
在有些情况下, 我们需要
控制某个特定行应该到哪个reducer
, 通常是为了进行后续的聚集操作;
distribute by字句可以做这件事.
distribute by类似于MR中的partition(自定义分区), 进行分区,结合sort by
使用
select * from emp distribute by deptno sort by empno desc;
不是相同deptno的数据分到一起, 而是根据分区字段(deptno)的Hash值,
20号和30号部门可以分到一个分区里面去。
hive要求Distribute by 语句要写在sort by语句之前
6.5.4 Cluster By
当distribute by和sort by字段相同时, 可以使用cluster by方式
但是只能是升序, 不能指定ASC或者DESC
hive (default)> select * from emp cluster by deptno;
hive (default)> select * from emp distribute by deptno sort by deptno;
6.6 分桶及抽样查询
6.6.1 分桶表数据存储
分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围划分。
分桶是将数据集分解成更容易管理的若干部分的另一个技术。
分区针对的是数据的存储路径;分桶针对的是数据文件。
- 创建分桶表
hive (default)> create table stu_buck(id int, name string)
> clustered by(id)
> into 4 buckets
> row format delimited
> fields terminated by '\t';
OK
Time taken: 0.217 seconds
- 导入数据
对于分桶表, 不能以load的方式导入数据
- 开启强制分桶(数据量过小的情况)
hive (default)> set hive.enforce.bucketing=true;- 通过子查询的方式导入数据
insert into table stu_buck select id, name from stu;
- 先创建一个普通表stu
hive (default)> create table stu(id int, name string)
> row format delimited fields terminated by '\t';
OK
Time taken: 0.19 seconds
- 向stu表中导入数据
hive (default)> load data local inpath '/home/yanlzh/data/student.txt' into table stu;
Loading data to table default.stu
OK
- 导入数据到分桶表,通过子查询的方式
hive (default)> set hive.enforce.bucketing=true;
hive (default)> insert into table stu_buck select id, name from stu;
Query ID = yanlzh_20191207131315_4421dd6f-e296-40c0-b35a-7d8188ecfe52
Total jobs = 1
Launching Job 1 out of 1
6.6.2 分桶抽样调查
对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。
hive (default)> select * from stu_buck tablesample(bucket 1 out of 4 on id);
注:
tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) 。
6.7 其他常见查询函数
6.7.1 空字段赋值
NVL(value, default_value)
- 如果员工的comm为NULL , 则用-1 代替
hive (default)> select comm,nvl(comm, -1) from emp;
OK
comm _c1
NULL -1.0
300.0 300.0
500.0 500.0
NULL -1.0
1400.0 1400.0
- 如果员工的comm为NULL , 则用领导id代替
hive (default)> select comm, nvl(comm,mgr) from emp;
OK
comm _c1
NULL 7902.0
300.0 300.0
500.0 500.0
NULL 7839.0
6.7.2 CASE… WHEN…
CASE col WHEN value THEN a ELSE b END
CASE sex WHEN ‘男’ THEN 1 ELSE 0 END
- 原始数据:
- 需求:
求出不同部门男女各有多少人.
dept_id male female
A 2 1
B 1 2
- 查询语句
hive (default)> select
> dept_id,
> sum(case sex when '男' then 1 else 0 end) male,
> sum(case sex when '女' then 1 else 0 end) female
> from
> emp_sex
> group by dept_id;
6.7.3 行转列(多行转集合)
concat(string A/col, string B/col, ...)
返回输入字符串连接后的结果,支持任意个输入字符串;concat_ws(separator, str1, str2, ...)
collect_set(col)
:
函数只接受基本数据类型, 它的主要作用是将某字段的值进行去重汇总, 产生array
类型的字段
- 原始数据
- 需求
把星座和血型一样的人归类到一起。结果如下:
cb names
射手座,A 大海|凤姐
白羊座,A 孙悟空|猪八戒
白羊座,B 宋宋
- 分析
cb这一列的结果是有 原始数据的两列连接得到的,
concat('constellation' , ',' ,'blood_type')
然后按照cb分组:group by cb
, 同时将每组的name字段的数据拼接(多行转集合)collect(name)
;
- 查询语句
hive (default)> select
> cb,
> concat_ws('|',collect_set(t1.name)) names
> from
> (select
> name,
> concat(constellation , ',' ,blood_type) cb
> from
> person_info) t1
> group by
> t1.cb;
6.7.4 列转行(集合转多行)
explode(col)
: 将hive一列中复杂的array或者map结构拆分成多行;lateral view
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
- 原始数据
- 需求
将电影分类中的数组数据展开。结果如下:
《疑犯追踪》 悬疑
《疑犯追踪》 动作
《疑犯追踪》 科幻
《疑犯追踪》 剧情
《Lie to me》 悬疑
《Lie to me》 警匪
《Lie to me》 动作
《Lie to me》 心理
《Lie to me》 剧情
《战狼2》 战争
《战狼2》 动作
《战狼2》 灾难
- 查询语句
hive (default)> select
> movie,
> category_name
> from
> movie_info lateral view explode(category) table_tmp as category_name;
- 列转行和行转列
hive (default)> select
> collect_set(movie) movies,
> t1.category_name
> from
> (select
> movie,
> category_name
> from
> movie_info lateral view explode(category) table_tmp as category_name
> )t1
> group by
> t1.category_name;
["《疑犯追踪》","《Lie to me》"] 剧情
["《疑犯追踪》","《Lie to me》","《战狼2》"] 动作
["《Lie to me》"] 心理
["《疑犯追踪》","《Lie to me》"] 悬疑
["《战狼2》"] 战争
["《战狼2》"] 灾难
["《疑犯追踪》"] 科幻
["《Lie to me》"] 警匪
6.7.5 窗口函数
语法:
UDAF() OVER (PARTITION BY col1, col2, .. ORDER BY col ROWS BETWEEN ... AND)
注:
- PARTITION By后可跟多个字段,order By只跟一个字段
- order by必须跟在partition by后;
- Rows必须跟在Order by子句
- (partition by … order by)可替换为(distribute by … sort by …)
- 关于OVER()
**
OVER()
**决定了聚合函数的聚合范围,默认对整个窗口中的数据进行聚合,聚合函数对每一条数据调用一次。
其中的ROWS BETWEEN... AND
为窗口子句,有如下形式:
(ROWS | RANGE)
BETWEEN (UNBOUNDED | [num]) PRECEDING
AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE)
BETWEEN CURRENT ROW
AND (CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
(ROWS | RANGE)
BETWEEN [num] FOLLOWING
AND (UNBOUNDED | [num]) FOLLOWING
CURRENT ROW: 当前行
n PRECEDING: 往前n行数据
n FOLLOWING: 往后n行数据
UNBOUNDED: 起点
UNBOUNDED PRECEDING 表示从前面的起点
UNBOUNDED FOLLOWING 表示到后面的终点
-
(1) 如果省略窗口子句,默认的窗口大小是 从当前分区的第一行到当前行
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
-
(2) 如果省略窗口子句和Order By ,则窗口大小是当前分区
ROW BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
窗口子句的作用:
通过使用partition by子句将数据进行了分区。如果想要对窗口进行更细的动态划分,就要引入窗口子句。
- 关于UDAF
- RANK()
生成数据项在分组中的排名,排名相等会在名次中留下空位。
1,2,3,3,5
- DENSE_RANK()
生成数据项在分组中的排名,排名相等会在名次中不会留下空位。
1,2,3,3,4
- ROW_NUMBER()
从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列;通常用于获取分组内排序第一的记录;获取一个session中的第一条refer等。
1,2,3,4,5
- NTILE(n)
把
有序分区
中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。NTILE不支持ROWS BETWEEN
应用: 查询前20%时间的订单信息
(按照订单时间排序,分为五组, 去NTILE这这列值为1 的数据即为20% )
- LAG(col,n,default_val)
前往第n行数据, 相对于当前行的第前N行数据
应用: 顾客的上次购买记录
- LEAD(col,n,default_val)
往后第n行数据,相对于当前行的第后N行数据
- FIRST_VALUE
取分组内排序后,截止到当前行,第一个值
- LAST_VALUE
取分组内排序后,截止到当前行,最后一个值
- SUM、AVG、MIN、MAX
- 关于应用场景:
(1)用于分区排序
(2)动态Group By
(3)Top N
(4)累计计算
(5)层次查询
6.7.6 Rank
第七章 函数
7.1 系统内置函数
7.2 自定义函数
- UDF(一进一出)
- UDAF(多进一出)
- UDTF(一进多出)
自定义函数编写步骤
- 导入Maven依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hive/hive-exec -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
- 创建一个类,继承UDF, 编写evaluate方法,实现业务逻辑
public class Lower extends UDF {
public String evaluate (final String s) {
if (s == null) {
return null;
}
return s.toLowerCase();
}
}
- 打jar包上传到服务器/opt/module/jars/udf.jar
- 将jar包添加到hive的classpath
hive (default)> add jar /opt/module/datas/udf.jar;
- 创建临时函数与开发好的java class关联
hive (default)> create temporary function mylower as "com.atguigu.hive.Lower";
- 在hql中使用自定义的函数
hive (default)> select ename, mylower(ename) lowername from emp;
第八章 压缩与存储
8.1 开启Map输出阶段压缩
开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下:
1.开启hive中间传输数据压缩功能
hive (default)>set hive.exec.compress.intermediate=true;
2.开启mapreduce中map输出压缩功能
hive (default)>set mapreduce.map.output.compress=true;
3.设置mapreduce中map输出数据的压缩方式
hive (default)>set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
8.2 开启Reduce输出阶段压缩
当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性hive.exec.compress.output控制着这个功能。用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。
1.开启hive最终输出数据压缩功能
hive (default)>set hive.exec.compress.output=true;
2.开启mapreduce最终输出数据压缩
hive (default)>set mapreduce.output.fileoutputformat.compress=true;
3.设置mapreduce最终数据输出压缩方式
hive (default)> set mapreduce.output.fileoutputformat.compress.codec =
org.apache.hadoop.io.compress.SnappyCodec;
4.设置mapreduce最终数据输出压缩为块压缩
hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;
5.测试一下输出结果是否是压缩文件
hive (default)> insert overwrite local directory
'/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;
8.3 文件输出格式
Hive支持的存储数据的格式主要有:
TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。
8.4 存储与压缩结合
8.4.1 修改Hadoop集群具有Snappy压缩方式
1.查看hadoop checknative命令使用
[yanlzh@node11 hadoop-2.7.2]$ hadoop
checknative [-a|-h] check native hadoop and compression libraries availability
2.查看hadoop支持的压缩方式
[yanlzh@node11 hadoop-2.7.2]$ hadoop checknative
17/12/24 20:32:52 WARN bzip2.Bzip2Factory: Failed to load/initialize native-bzip2 library system-native, will use pure-Java version
17/12/24 20:32:52 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
Native library checking:
hadoop: true /opt/module/hadoop-2.7.2/lib/native/libhadoop.so
zlib: true /lib64/libz.so.1
snappy: false
lz4: true revision:99
bzip2: false
3.将编译好的支持Snappy压缩的hadoop-2.7.2.tar.gz包导入到hadoop102的/opt/software中
4.解压hadoop-2.7.2.tar.gz到当前路径
[yanlzh@node11 software]$ tar -zxvf hadoop-2.7.2.tar.gz
5.进入到/opt/software/hadoop-2.7.2/lib/native路径可以看到支持Snappy压缩的动态链接库
[yanlzh@node11 native]$ pwd
/opt/software/hadoop-2.7.2/lib/native
[yanlzh@node11 native]$ ll
-rw-r--r--. 1 atguigu atguigu 472950 9月 1 10:19 libsnappy.a
-rwxr-xr-x. 1 atguigu atguigu 955 9月 1 10:19 libsnappy.la
lrwxrwxrwx. 1 atguigu atguigu 18 12月 24 20:39 libsnappy.so -> libsnappy.so.1.3.0
lrwxrwxrwx. 1 atguigu atguigu 18 12月 24 20:39 libsnappy.so.1 -> libsnappy.so.1.3.0
-rwxr-xr-x. 1 atguigu atguigu 228177 9月 1 10:19 libsnappy.so.1.3.0
6.拷贝/opt/software/hadoop-2.7.2/lib/native里面的所有内容到开发集群的/opt/module/hadoop-2.7.2/lib/native路径上
[yanlzh@node11 native]$ cp ../native/* /opt/module/hadoop-2.7.2/lib/native/
7.分发集群
[yanlzh@node11 lib]$ xsync native/
8.再次查看hadoop支持的压缩类型
[yanlzh@node11 hadoop-2.7.2]$ hadoop checknative
17/12/24 20:45:02 WARN bzip2.Bzip2Factory: Failed to load/initialize native-bzip2 library system-native, will use pure-Java version
17/12/24 20:45:02 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
Native library checking:
hadoop: true /opt/module/hadoop-2.7.2/lib/native/libhadoop.so
zlib: true /lib64/libz.so.1
snappy: true /opt/module/hadoop-2.7.2/lib/native/libsnappy.so.1
lz4: true revision:99
bzip2: false
9.重新启动hadoop集群和hive
8.4.2 测试存储和压缩
1.创建一个非压缩的的ORC存储方式
(1)建表语句
create table log_orc_none(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc tblproperties ("orc.compress"="NONE");
(2)插入数据
hive (default)> insert into table log_orc_none select * from log_text ;
(3)查看插入后数据
hive (default)> dfs -du -h /user/hive/warehouse/log_orc_none/ ;
7.7 M /user/hive/warehouse/log_orc_none/000000_0
2.创建一个SNAPPY压缩的ORC存储方式
(1)建表语句
create table log_orc_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc tblproperties ("orc.compress"="SNAPPY");
(2)插入数据
hive (default)> insert into table log_orc_snappy select * from log_text ;
(3)查看插入后数据
hive (default)> dfs -du -h /user/hive/warehouse/log_orc_snappy/ ;
3.8 M /user/hive/warehouse/log_orc_snappy/000000_0
3.上一节中默认创建的ORC存储方式,导入数据后的大小为
2.8 M /user/hive/warehouse/log_orc/000000_0
比Snappy压缩的还小。原因是orc存储文件默认采用ZLIB压缩,ZLIB采用的是deflate压缩算法。比snappy压缩的小。
4.存储方式和压缩总结
在实际的项目开发当中,hive表的数据存储格式一般选择:orc或parquet。压缩方式一般选择snappy,lzo
。
第九章 企业级优化
9.1 Fetch 抓取
Fetch抓取是指,
Hive中对某些情况的查询可以不必使用MapReduce计算
。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台。
在hive-default.xml.template文件中hive.fetch.task.conversion
默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
9.2 本地模式
大多数的Hadoop Job是需要Hadoop提供的完整的可扩展性来处理大数据集的。不过,
有时Hive的输入数据量是非常小的。在这种情况
下,为查询触发执行任务消耗的时间可能会比实际job的执行时间要多的多
。对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务
。对于小数据集
,执行时间可以明显被缩短。
用户可以通过设置hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化,默认是false。
9.3 表的优化
9.3.1 小表 大表Join
将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用map join让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce。
实际测试发现:新版的hive已经对小表JOIN大表和大表JOIN小表进行了优化。小表放在左边和右边已经没有明显区别。
9.3.2 MapJoin(小表Join大表)
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:
在Reduce阶段完成join。容易发生数据倾斜
。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
1.开启MapJoin参数设置
(1)设置自动选择Mapjoin
hive (default)> set hive.auto.convert.join = true; 默认为true
(2)大表小表的阈值设置(默认25M一下认为是小表):
hive (default)> set hive.mapjoin.smalltable.filesize=25000000;
2.案例实操:
(1)开启Mapjoin功能
set hive.auto.convert.join = true; 默认为true
(2)执行小表JOIN大表语句
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s
join bigtable b
on s.id = b.id;
Time taken: 24.594 seconds
(3)执行大表JOIN小表语句
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable b
join smalltable s
on s.id = b.id;
Time taken: 24.315 seconds
9.3.3 Group By
默认情况下, Map阶段同一key数据分发给一个reduce, 当一个key数据过大是就倾斜了;
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。
1.开启Map端聚合参数设置
(1)是否在Map端进行聚合,默认为True
set hive.map.aggr = true
(2)在Map端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000
(3)有数据倾斜的时候进行负载均衡(默认是false)
set hive.groupby.skewindata = true
当选项设定为 true,生成的查询计划会有
两个MR Job
。
第一个MR Job中,Map的输出结果会随机分布到Reduce中
,每个Reduce做部分聚合操作
,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中
,从而达到负载均衡的目的
;
第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。
hive (default)> select deptno from emp group by deptno;
Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 23.68 sec HDFS Read: 19987 HDFS Write: 9 SUCCESS
Total MapReduce CPU Time Spent: 23 seconds 680 msec
OK
deptno
10
20
30
优化以后
hive (default)> set hive.groupby.skewindata = true;
hive (default)> select deptno from emp group by deptno;
Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 28.53 sec HDFS Read: 18209 HDFS Write: 534 SUCCESS
Stage-Stage-2: Map: 1 Reduce: 5 Cumulative CPU: 38.32 sec HDFS Read: 15014 HDFS Write: 9 SUCCESS
Total MapReduce CPU Time Spent: 1 minutes 6 seconds 850 msec
OK
deptno
10
20
30
9.3.4 Count(Distinct)去重统计
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT的全聚合操作,即使设定了reduce task个数,set mapred.reduce.tasks=100;
hive也只会启动一个reducer
。,这就造成一个Reduce处理的数据量太大,导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换
:
9.3.6 笛卡尔积
尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。
9.3.7 动态分区调整
关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,使用Hive的动态分区,需要进行相应的配置。
开启动态分区参数设置
(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