Hive是基于 Hadoop 的一个【数据仓库工具】,可以将结构化和半结构化的数据文件映射为一张数据库 表,并提供简单的 sql 查询功能。
数据仓库的一个比较公认的定义是一个面向主题的(Subject Oriented)、集成的(Integrated)、相对稳定的(Non-Volatile)、反映历史变化的(Time Variant)的数据集合,用于支持管理决策。
数据仓库的体系结构通常包含4个层次:数据源、数据存储和管理、数据服务、数据应用。
1) **数据源:数据仓库的数据来源,**包含外部数据、现有业务的(OLTP,联机事务处理)系统和文档资料等。
2)数据存储和管理:主要涉及对数据的存储和管理,包括数据仓库、数据集市、数据仓库监视、运行与维护的元数据管理等。
3)数据服务:为前端工具和应用 提供数据服务。可以直接从数据仓库中获取数据 提供前端应用使用。
4)数据应用:直接面向最终用户,包括数据查询工具、数据分析工具、数据挖掘工具等。
可扩展性
Hive可以自由的扩展集群的规模,一般情况下不需要重启服务 。
延伸性
Hive支持自定义函数,用户可以根据自己的需要来实现自己的函数 。
采用批处理方式处理海量数据
Hive需要把HiveQL语句转换成MapReduce任务进行运行; 数据仓库存储的是静态数据,对静态数据的分析适合采用批处理方式,不需要 快速响应给出结果,而且数据本身也不会频繁变化。
容错
即使节点出现错误,SQL仍然可以完成执行。
提供适合数据仓库操作的工具
Hive本身提供了一系列对数据进行提取转化加载的工具,可以存储、查询和分 析存储在Hadoop中的大规模数据;
Hive依赖于HDFS 存储数据
HDFS作为高可靠性的底层存储,用来存储海量数据
Hive依赖于MapReduce 处理数据
MapReduce对这些海量数据进行处理,实现高性能计算,用HiveQL语句 编写的处理逻辑最终均要转化为MapReduce任务来运行
Pig可以作为Hive的替代工具
pig是一种数据流语言和运行环境,适合用于Hadoop和MapReduce平台 上查询半结构化数据集。常用于ETL过程的一部分,即将外部数据装载到 Hadoop集群中,然后转换为用户期待的数据格式
HBase 提供数据的实时访问
HBase一个面向列的、分布式的、可伸缩的数据库,它可以提供数据的实 时访问功能,而Hive只能处理静态数据,主要是BI报表数据,所以HBase 与Hive的功能是互补的,它实现了Hive不能提供功能。
Hive与传统数据库的区别主要体现在以下几个方面:
Hive主要由以下3个模块组成:用户接口模块、驱动模块以及元数据存储模块。
Hive允许client连接的方式有三个CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问 hive)。JDBC访问时中间件Thrift软件框架,跨语言服务开发。DDL DQL DML,整体仿写一套SQL语句。
元数据包括表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是 外部表)、表的数据所在目录等。
元数据存储在数据库中,默认存在自带的derby数据库(单用户局限性)中,推荐使用Mysql进行存储。
Hive的数据存储在HDFS中,计算由MapReduce完成。HDFS和MapReduce是源码级别上的整合,两者 结合最佳。解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计 划的生成。
Hive元数据库中一些重要的表结构及用途,方便Impala、SparkSQL、Hive等组件访问元数据库的理解。
1、存储Hive版本的元数据表(VERSION),该表比较简单,但很重要。
2、Hive数据库相关的元数据表(DBS、DATABASE_PARAMS)
3、Hive表和视图相关的元数据表
4、Hive文件存储信息相关的元数据表
5、Hive表字段相关的元数据表
节点\功能 | metastore | hiveserver2 | client |
---|---|---|---|
node01 | * | * | |
node02 | * | ||
node03 | * |
PS: 安装前 请确认当前集群已经安装了Mysql数据库、ZooKeeper和Hadoop的Ha+Yarn
如果未安装:
链接: MySQL安装 :. https://blog.csdn.net/weixin_43660536/article/details/118033294
链接: ZooKeeper安装:. https://blog.csdn.net/weixin_43660536/article/details/118369963
链接: hadoop ha安装:. https://blog.csdn.net/weixin_43660536/article/details/118358298
链接: yarn搭建: . https://blog.csdn.net/weixin_43660536/article/details/118540991
下载地址
http://archive.apache.org/dist/hive/
[root@node01 ~]# tar -zxvf apache-hive-3.1.2-bin.tar.gz
[root@node01 ~]# mv apache-hive-3.1.2-bin /opt/yjx/
[root@node01 ~]# cd /opt/yjx/apache-hive-3.1.2-bin/conf
准备驱动包
配置hive-env.sh
[root@node01 conf]# cp hive-env.sh.template hive-env.sh
[root@node01 conf]# vim hive-env.sh
export HADOOP_HOME=/opt/yjx/hadoop-3.1.2/
export HIVE_CONF_DIR=/opt/yjx/apache-hive-3.1.2-bin/conf
export HIVE_AUX_JARS_PATH=/opt/yjx/apache-hive-3.1.2-bin/lib
创建hive-site.xml
[root@node01 conf]# cp hive-default.xml.template hive-site.xml
[root@node01 conf]# vim hive-site.xml
删除多余的配置文件 6897dd
<property>
<name>javax.jdo.option.ConnectionURLname>
<value>jdbc:mysql://node01:3306/hive?createDatabaseIfNotExist=truevalue>
property>
<property>
<name>javax.jdo.option.ConnectionDriverNamename>
<value>com.mysql.jdbc.Drivervalue>
property>
<property>
<name>javax.jdo.option.ConnectionUserNamename>
<value>rootvalue>
property>
<property>
<name>javax.jdo.option.ConnectionPasswordname>
<value>123456value>
property>
<property>
<name>datanucleus.schema.autoCreateAllname>
<value>truevalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
<property>
<name>hive.cli.print.headername>
<value>truevalue>
property>
<property>
<name>hive.cli.print.current.dbname>
<value>truevalue>
property>
<property>
<name>hive.server2.webui.hostname>
<value>node01value>
property>
<property>
<name>hive.server2.webui.portname>
<value>10002value>
property>
<property>
<name>hive.metastore.warehouse.dirname>
<value>/hive/warehousevalue>
property>
修改core-site.xml
[root@node01 conf]# vim /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml
后面添加配置信息
<property>
<name>hadoop.proxyuser.root.hostsname>
<value>*value>
property>
<property>
<name>hadoop.proxyuser.root.groupsname>
<value>*value>
property>
[root@node01 ~]# mkdir -p /opt/yjx/apache-hive-3.1.2-bin/logs
[root@node01 conf]# cp hive-log4j2.properties.template hive-log4j2.properties
[root@node01 conf]# vim hive-log4j2.properties
修改配置
property.hive.log.dir = /opt/yjx/apache-hive-3.1.2-bin/logs
Mysql驱动添加到hive的lib目录下
[root@node01 ~]# cp ~/mysql-connector-java-5.1.32-bin.jar /opt/yjx/apache-hive-3.1.2-bin/lib/
Guava包
首先要删除hadoop中的guava-*.jar包
[root@node01 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
[root@node01 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
将Hive的Guava拷贝给Hive
[root@node01 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
[root@node01 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
vim /etc/profile
export HIVE_HOME=/opt/yjx/apache-hive-3.1.2-bin
export PATH=$HIVE_HOME/bin:$PATH
hive文件夹
[root@node02 ~]# scp -r root@node01:/opt/yjx/apache-hive-3.1.2-bin /opt/yjx/
[root@node03 ~]# scp -r root@node01:/opt/yjx/apache-hive-3.1.2-bin /opt/yjx/
环境变量
[root@node01 ~]# scp /etc/profile root@node02:/etc/profile
[root@node01 ~]# scp /etc/profile root@node03:/etc/profile
【node123】source /etc/profile
core-stie.xml
[root@node01 ~]# scp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml root@node02:/opt/yjx/hadoop-3.1.2/etc/hadoop/
[root@node01 ~]# scp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml root@node03:/opt/yjx/hadoop-3.1.2/etc/hadoop/
jar包
[root@node02 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
[root@node02 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
[root@node03 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
[root@node03 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
[root@node02 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
[root@node02 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
[root@node03 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
[root@node03 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
选取node03为客户端节点
[node03] vim /opt/yjx/apache-hive-3.1.2-bin/conf/hive-site.xml
<property>
<name>hive.metastore.warehouse.dirname>
<value>/hive/warehousevalue>
property>
<property>
<name>hive.cli.print.headername>
<value>truevalue>
property>
<property>
<name>hive.cli.print.current.dbname>
<value>truevalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
<property>
<name>datanucleus.schema.autoCreateAllname>
<value>truevalue>
property>
<property>
<name>hive.metastore.urisname>
<value>thrift://node01:9083value>
property>
启动Zookeeper
【123】zkServer.sh start
启动Hdfs+Yarn
[root@node01 ~]# start-all.sh
初始化数据库
启动Hive
//前台运行
[root@node01 ~]# hive --service metastore
//后台运行
[root@node01 ~]# nohup hive --service metastore > /dev/null 2>&1 &
启动HiveServer2(可启动可不启动)
//前台启动
[root@node01 ~]# hiveserver2
//后台启动
[root@node01 ~]# nohup hiveserver2 > /dev/null 2>&1 &
连接
[root@node03 ~]# beeline -u jdbc:hive2://node01:10000 -n root
连接成功,测试
show databases;
create databases hive;
show databases;
// 查看是否创建成功;
退出hive,Ctrl+C停止Hive进程 ;
//关闭hadoop与yarn
[root@node01 ~]# stop-all.sh
//关闭ZooKeeper
[123]# zkServer.sh start
//关机
[123]# shutdown -h now
拍摄快照
1)第一种交互方式
shell交互Hive,用命令hive启动一个hive的shell命令行,在命令行中输入sql或者命令来和Hive交互。
服务端启动metastore服务(后台启动):nohup hive --service metastore > /dev/null 2>&1 &
进入命令:hive
退出命令行:quit;
2)第二种交互方式
Hive启动为一个服务器,对外提供服务,其他机器可以通过客户端通过协议连接到服务器,来完成访问操作,这是生产环境用法最多的
hadoop fs -chmod -R 777 /yjx
服务端启动hiveserver2服务:
nohup hive --service metastore > /dev/null 2>&1 &
nohup hiveserver2 > /dev/null 2>&1 &
需要稍等一下,启动服务需要时间:
进入命令:1)先执行: beeline ,在执行: ! connect jdbc:hive2://node01:10000
2)或者直接执行: beeline -u jdbc:hive2://node01:10000 -n root
退出命令行:!exit
3)第三种交互方式
bin/hive -e "show databases;"
vim hive.sql
use myhive;
select * from test;
保存退出
hive -f hive.sql
特点:执行完sql后,回到linux命令行。
1)创建一个数据库,数据库在HDFS上的默认存储路径是/hive/warehouse/*.db。
create database shop;
2)避免要创建的数据库已经存在错误,增加if not exists判断。(标准写法)
create database if not exists shop;
create database if not exists school location '/school.db';
数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置。
alter database school set dbproperties('createtime'='20201213');
1)显示数据库(show)
show databases;
2)可以通过like进行过滤
show databases like 's*';
desc database school;
4)切换数据库(use)
use school;
1)最简写法
drop database school;
2)如果删除的数据库不存在,最好使用if exists判断数据库是否存在。否则会报错:FAILED: SemanticException [Error 10072]: Database does not exist: db_hive
drop database if exists school;
3)如果数据库不为空,使用cascade命令进行强制删除。报错信息如下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.)
drop database if exists school cascade;
类型 | Java数据类型 | 描述 |
---|---|---|
TINYINT | byte | 8位有符号整型。取值范围:-128~127。 |
SMALLINT | short | 16位有符号整型。取值范围:-32768~32767。 |
INT | int | 32位有符号整型。取值范围:-2 31 ~2 31 -1。 |
BIGINT | long | 64位有符号整型。取值范围:-2 63 +1~2 63 -1。 |
BINARY | 二进制数据类型,目前长度限制为8MB。 | |
FLOAT | float | 32位二进制浮点型。 |
DOUBLE | double | 64位二进制浮点型。 |
DECIMAL(precision,scale) | 10进制精确数字类型。precision:表示最多可以表示多少位的数字。取值范围:1 <= precision <= 38 。scale:表示小数部分的位数。取值范围: 0 <= scale <= 38 。如果不指定以上两个参数,则默认为decimal(10,0) 。 |
|
VARCHAR(n) | 变长字符类型,n为长度。取值范围:1~65535。 | |
CHAR(n) | 固定长度字符类型,n为长度。最大取值255。长度不足则会填充空格,但空格不参与比较。 | |
STRING | string | 字符串类型,目前长度限制为8MB。 |
DATE | 日期类型,格式为yyyy-mm-dd 。取值范围:0000-01-01~9999-12-31。 |
|
DATETIME | 日期时间类型。取值范围:0000-01-01 00:00:00.000~9999-12-31 23.59:59.999,精确到毫秒。 | |
TIMESTAMP | 与时区无关的时间戳类型。取值范围:0000-01-01 00:00:00.000000000~9999-12-31 23.59:59.999999999,精确到纳秒。说明 对于部分时区相关的函数,例如cast( as string) ,要求TIMESTAMP按照与当前时区相符的方式来展现。 |
|
BOOLEAN | boolean | BOOLEAN类型。取值:True、False。 |
类型 | 定义方法 | 构造方法 |
---|---|---|
ARRAY | array |
array(1, 2, 3)``array(array(1, 2), array(3, 4)) |
MAP | map |
map(“k1”, “v1”, “k2”, “v2”)``map(1S, array(‘a’, ‘b’), 2S, array(‘x’, ‘y’)) |
STRUCT | struct |
named_struct(‘x’, 1, ‘y’, 2)``named_struct(‘field1’, 100L, ‘field2’, array(1, 2), ‘field3’, map(1, 100, 2, 200)) |
Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套。还有一个uniontype< 所有类型,所有类型… > 。
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]
字段解释说明:
- CREATE TABLE
创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
- EXTERNAL
关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION)
创建内部表时,会将数据移动到数据仓库指向的路径(默认位置);
创建外部表时,仅记录数据所在的路径,不对数据的位置做任何改变。在
删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
- COMMENT:
为表和列添加注释。
- PARTITIONED BY
创建分区表
- CLUSTERED BY
创建分桶表
- SORTED BY
不常用
- 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的简称,目的是用于序列化和反序列化。
- STORED AS指定存储文件类型
常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)
如果文件数据是纯文本,可以使用STORED AS TEXTFILE。
如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
- LOCATION :
指定表在HDFS上的存储位置。
- LIKE
允许用户复制现有的表结构,但是不复制数据。
根据数据创建表结构
案例1:简单用户信息
1,admin,123456,男,18
2,zhangsan,abc123,男,23
3,lisi,654321,女,16
create external table t_user(
id int,
uname string,
pwd string,
gender string,
age int
)
row format delimited fields terminated by ','
lines terminated by '\n';
--载入数据代码
load data inpath '/yjx/user.txt' into table t_user;
案例2:复杂人员信息
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
create table IF NOT EXISTS t_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 keys terminated by ':'
lines terminated by '\n';
--载入数据代码
load data inpath '/yjx/person.txt' into table t_person;
show tables;
show tables like 'u';
desc t_person;
desc formatted t_person;
内部表(同时修改文件目录)外部表(因为目录是共享的,所以不会修改目录名称)
alter table old_table_name rename to new_table_name;
alter table t_old rename to t_new;
desc test_new;
alter table test_new add columns (education string);
desc test_new;
alter table test_new change education educationnew string;
drop table test_new;
当创建好表的时候,HDFS会在当前表所属的库中创建一个文件夹
当设置表路径的时候,如果直接指向一个已有的路径,可以直接去使用文件夹中的数据
当load数据的时候,就会将数据文件存放到表对应的文件夹中
而且数据一旦被load,就不能被修改
我们查询数据也是查询文件中的文件,这些数据最终都会存放到HDFS
当我们删除表的时候,表对应的文件夹会被删除,同时数据也会被删除
外部表说明
操作案例:
分别创建dept,emp,salgrade。并加载数据。
创建数据文件存放的目录
hdfs dfs -mkdir -p /yjx/dept
hdfs dfs -mkdir -p /yjx/emp
hdfs dfs -mkdir -p /yjx/salgrade
创建dept表
CREATE EXTERNAL TABLE IF NOT EXISTS dept (
DEPTNO int,
DNAME varchar(255),
LOC varchar(255)
) row format delimited fields terminated by ','
location '/yjx/dept';
10,ACCOUNTING,NEW YORK
20,RESEARCH,DALLAS
30,SALES,CHICAGO
40,OPERATIONS,BOSTON
创建emp表
CREATE EXTERNAL TABLE IF NOT EXISTS emp (
EMPNO int,
ENAME varchar(255),
JOB varchar(255),
MGR int,
HIREDATE date,
SAL decimal(10,0),
COMM decimal(10,0),
DEPTNO int
) row format delimited fields terminated by ','
location '/yjx/emp';
7369,SMITH,CLERK,7902,1980-12-17,800,null,20
7499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,30
7521,WARD,SALESMAN,7698,1981-02-22,1250,500,30
7566,JONES,MANAGER,7839,1981-04-02,2975,null,20
7654,MARTIN,SALESMAN,7698,1981-09-28,1250,1400,30
7698,BLAKE,MANAGER,7839,1981-05-01,2850,null,30
7782,CLARK,MANAGER,7839,1981-06-09,2450,null,10
7788,SCOTT,ANALYST,7566,1987-07-13,3000,null,20
7839,KING,PRESIDENT,null,1981-11-17,5000,null,10
7844,TURNER,SALESMAN,7698,1981-09-08,1500,0,30
7876,ADAMS,CLERK,7788,1987-07-13,1100,null,20
7900,JAMES,CLERK,7698,1981-12-03,950,null,30
7902,FORD,ANALYST,7566,1981-12-03,3000,null,20
7934,MILLER,CLERK,7782,1982-01-23,1300,null,10
创建salgrade表
CREATE EXTERNAL TABLE IF NOT EXISTS salgrade (
GRADE int,
LOSAL int,
HISAL int
) row format delimited fields terminated by ','
location '/yjx/salgrade';
1,700,1200
2,1201,1400
3,1401,2000
4,2001,3000
5,3001,9999
基本语法
load data [local] inpath 'datapath' [overwrite] into table student [partition (partcol1=val1,…)];
--load data
加载数据
--[local]
本地,不加Local就是从HDFS,如果是HDFS,将会删除掉原来的数据
--inpath
数据的路径
--'datapath'
具体的路径,要参考本地还是HDFS
--[overwrite]
覆盖
--into table
加入到表
--student
表的名字
--[partition (partcol1=val1,…)]
分区
加载linux本地数据
-- 切记必须和hiveserver2在同一个节点才可以上传否则
-- SemanticException Line 1:23 Invalid path ''/root/d3.txt'': No files matching path file
load data local inpath '/root/user.txt' into table t_user;
load data inpath '/yjx/user.txt' into table t_user;
load data inpath '/yjx/user.txt' overwrite into table t_user;
通过查询插入数据
创建表
create table t_user1(
id int,
uname string
)
row format delimited fields terminated by ','
lines terminated by '\n';
create table t_user2(
id int,
pwd string
)
row format delimited fields terminated by ','
lines terminated by '\n';
插入查询结果
--将查询结果插入一张表
insert overwrite table t_user1 select id,uname from t_user;
insert overwrite table t_user2 select id,pwd from t_user;
--将查询结果一次性存放到多张表
from t_user
insert overwrite table t_user1 select id,uname
insert overwrite table t_user2 select id,pwd;
将表中的数据备份
//创建存放数据的目录
mkdir -p /root/yjx
//导出查询结果的数据(导出到Node01上)
insert overwrite local directory '/root/person_data' select * from t_person;
-- 创建存放数据的目录
mkdir -p /root/yjx
-- 导出查询结果的数据
insert overwrite local directory '/root/yjx/person'
ROW FORMAT DELIMITED fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
lines terminated by '\n'
select * from t_person;
-- 创建存放数据的目录
hdfs dfs -mkdir -p /yjx/copy
-- 导出查询结果的数据
insert overwrite directory '/yjx/copy/user'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
select * from t_user;
直接使用HDFS命令保存表对应的文件夹
// 创建存放数据的目录
hdfs dfs -mkdir -p /yjx/person
// 使用HDFS命令拷贝文件到其他目录
hdfs dfs -cp /hive/warehouse/t_person/* /yjx/person
将表结构和数据同时备份
//创建存放数据的目录
hdfs dfs -mkdir -p /yjx/copy
//导出查询结果的数据
export table t_person to '/yjx/copy';
drop table t_person;
import from '/yjx/copy';
在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天或者每小时切分成一个个小的文件,这样去操作小的文件就会容易很多了。
假如现在我们公司一天产生3亿的数据量,那么为了方便管理和查询,
CREATE TABLE IF NOT EXISTS t_student (
sno int,
sname string
) partitioned by(grade int)
row format delimited fields terminated by ',';
-- 分区的字段不要和表的字段相同。相同会报错error10035
1,zhangsanfeng01,1
2,zhangsanfeng02,1
3,zhangsanfeng03,1
4,zhangsanfeng04,1
5,zhangsanfeng05,1
6,zhangsanfeng06,1
19,zhangsanfeng19,4
20,zhangsanfeng20,4
21,zhangsanfeng21,4
-- 载入数据
-- 将相应年级一次导入
load data inpath '/yjx/student.txt' into table t_student partition(grade=1);
CREATE TABLE IF NOT EXISTS t_teacher (
tno int,
tname string
) partitioned by(grade int,clazz int)
row format delimited fields terminated by ',';
--注意:前后两个分区的关系为父子关系,也就是grade文件夹下面有多个clazz子文件夹。
1,jueyuan01,1,1
2,jueyuan02,1,1
3,jueyuan03,1,2
4,jueyuan04,1,2
5,jueyuan05,1,3
6,jueyuan06,1,3
7,jueyuan07,2,1
8,jueyuan08,2,1
9,jueyuan09,2,2
--载入数据
load data inpath '/yjx/teacher11.txt' into table t_teacher partition(grade=1,class=1);
select * from t_student where grade = 1 ;
show partitions t_student;
alter table t_student add partition (day='99990102');
alter table t_student add partition (day='99990103') location '99990103';
alter table salgrade2 drop partition (day='99990102');
动态分区(DP)dynamic partition
静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。
详细来说,静态分区的列是在编译时期通过用户传递来决定的;动态分区只有在SQL执行时才能决定。
开启动态分区首先要在hive会话中设置如下的参数
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
其余的参数详细配置如下
设置为true表示开启动态分区的功能(默认为false)
--hive.exec.dynamic.partition=true;
设置为nonstrict,表示允许所有分区都是动态的(默认为strict)
-- hive.exec.dynamic.partition.mode=nonstrict;
每个mapper或reducer可以创建的最大动态分区个数(默认为100)
比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错
--hive.exec.max.dynamic.partition.pernode=100;
一个动态分区创建可以创建的最大动态分区个数(默认值1000)
--hive.exec.max.dynamic.partitions=1000;
全局可以创建的最大文件个数(默认值100000)
--hive.exec.max.created.files=100000;
当有空分区产生时,是否抛出异常(默认false)
-- hive.error.on.empty.partition=false;
--创建分区表
CREATE TABLE IF NOT EXISTS t_student_d (
sno int,
sname string
) partitioned by (grade int,clazz int)
row format delimited fields terminated by ',';
--创建外部表
CREATE EXTERNAL TABLE IF NOT EXISTS t_student_e (
sno int,
sname string,
grade int,
clazz int
)
row format delimited fields terminated by ','
location "/yjx/student";
如果静态分区的话,我们插入数据必须指定分区的值。
如果想要插入多个班级的数据,我要写很多SQL并且执行24次很麻烦。
而且静态分区有可能会产生数据错误问题
-- 会报错
insert overwrite table t_student partition (grade=1) select * from t_student_e where grade=1;
如果使用动态分区,动态分区会根据select的结果自动判断数据应该load到哪儿分区去。
insert overwrite table t_student_d partition (grade,clazz) select * from t_student_e ;
方便抽样
提高join查询效率
-- 开启分桶功能
set hive.enforce.bucketing=true;
-- 设置Reduce个数
-- 我们需要确保reduce 的数量与表中的bucket 数量一致
-- bucket个数会决定在该表或者该表的分区对应的hdfs目录下生成对应个数的文件,而mapreduce的个数是根据文件块的个数据确定的map个数。
set mapreduce.job.reduce=3;
-- 创建表
CREATE TABLE t_citizen_bucket(
idcard int,
pname string,
province int
)clustered by(idcard) sorted by (pname desc) into 16 buckets
row format delimited fields terminated by ','
lines terminated by '\n';
create EXTERNAL table t_citizen(
idcard int,
pname string,
province int
)row format delimited fields terminated by ','
lines terminated by '\n'
location '/yjx/citizen';
-- 数据导入
for (int i = 1000; i < 10000; i++) {
System.out.println(i + "," + "admin" + (new Random().nextInt(89999) + 10000) + "," + i % 34);
}
-- 将外部表的数据导入到分桶表
insert overwrite table t_citizen_bucket select * from t_citizen ;
-- 该方式允许Hive随机抽取N行数据,数据总量的百分比(n百分比)或N字节的数据。
SELECT * FROM <Table_Name> TABLESAMPLE(N PERCENT|ByteLengthLiteral|N ROWS) s;
1) tablesample(n percent) 根据hive表数据的大小按比例抽取数据,并保存到新的hive表中。如:抽取原hive表中10%的数据
注意:测试过程中发现,select语句不能带where条件且不支持子查询,可通过新建中间表或使用随机抽样解决
create table xxx_new as select * from xxx tablesample(10 percent)
2)tablesample(n M) 指定抽样数据的大小,单位为M。
3)tablesample(n rows) 指定抽样数据的行数,其中n代表每个map任务均取n行数据
-- hive另外一种按照抽样百分比进行抽样的方式,该种方式基于行数,按照输入路径下的数据块的百分比进行抽样。
-- 这种抽样的最小单元是一个hdfs数据块,如果表的数据大小小于普通块大小128M,将返回所有行。
-- 基于百分比的抽样方式提供了一个变量,用于控制基于数据块的调优种子信息:
-- tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)
-- 分桶语句中的分母表示的是数据将会被散列的桶的个数,分子表示将会选择的桶的个数。
-- x表示从哪个bucket开始抽取。
-- 例如,table总bucket数为32,tablesample(bucket 3 out of 16)
-- 表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据
-- y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。
-- 例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据
select * from t_citizen_bucket tablesample(bucket 1 out of 16 on idcard);
select * from t_citizen_bucket tablesample(bucket 2 out of 4 on idcard);
-- 使用RAND()函数和LIMIT关键字来获取样例数据,使用DISTRIBUTE和SORT关键字来保证数据是随机分散到mapper和reducer的。
-- ORDER BY RAND()语句可以获得同样的效果,但是性能没这么高。
SELECT * FROM <Table_Name> DISTRIBUTE BY RAND() SORT BY RAND() LIMIT <N rows to sample>;
select * from t_citizen_bucket DISTRIBUTE BY RAND() SORT BY RAND() LIMIT 10;
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 [offset,] rows]
select * from 表名 order by 字段名1[,别名2...];
sort by 不是全局排序,其在数据进入reducer前完成排序。
如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by 只保证每个reducer的输出有序,不保证全局有序。
设置reduce个数
set mapreduce.job.reduce=3;
set mapred.reduce.tasks=3;
查看reduce个数
set mapreduce.job.reduce;
排序
select * from 表名 sort by 字段名[,字段名...];
distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
类似MR中partition,进行分区,结合sort by使用。(注意:distribute by 要在sort by之前)
对于distrbute by 进行测试,一定要多分配reduce进行处理,否则无法看到distribute by的效果。
设置reduce个数
set mapreduce.job.reduce=7;
select * from 表名 distribute by 字段名[,字段名...];
select * from 表名 sort cluster by 字段名[,字段名...];
select * from 表名 distribute by 字段名[,字段名...] sort by 字段名[,字段名...];
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
-- 1.查看系统自带函数
show functions;
-- 2.显示自带的函数的用法
desc function upper;
-- 3.详细显示自带的函数的用法
desc function extended upper;
关系操作符:包括 = 、 <> 、 <= 、>=等
算数操作符:包括 + 、 - 、 *、/等
逻辑操作符:包括AND 、 && 、 OR 、 || 等
复杂类型构造函数:包括map、struct、create_union等
复杂类型操作符:包括A[n]、Map[key]、S.x
数学操作符:包括ln(double a)、sqrt(double a)等
集合操作符:包括size(Array)、sort_array(Array)等
类型转换函数: binary(string|binary)、cast(expr as )
日期函数:包括from_unixtime(bigint unixtime[, string format])、unix_timestamp()等
条件函数:包括if(boolean testCondition, T valueTrue, T valueFalseOrNull)等
字符串函数:包括acat(string|binary A, string|binary B…)等
其他:xpath、get_json_objectscii(string str)、con
-- UDTF 进一出多
-- explode 可以将一组数组的数据变成一列表
select explode(split(列名,"数据的分隔符")) from 表名;
-- lateral view 表生成函数,可以将explode的数据生成一个列表
select id,name,列名 from 表1,lateral view explode(split(表1.列名,"数据的分隔符"))新列名 as 别列名;
-- UDTF 进多出一
-- collect_set()和collect_list()都是对多列转成一行,区别就是list里面可重复而set里面是去重的
-- concat_ws(':',collect_set(type)) ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
select 字段名,concat_ws(':',collect_set(列名)) as 别名 from 表名 group by id;
-- 创建数据库表
create table t_movie1(
id int,
name string,
types string
)
row format delimited fields terminated by ','
lines terminated by '\n';
-- 电影数据 movie1.txt
-- 加载数据到数据库 load data inpath '/yjx/movie1.txt' into table t_movie1;
1,这个杀手不太冷,剧情-动作-犯罪
2,七武士,动作-冒险-剧情
3,勇敢的心,动作-传记-剧情-历史-战争
4,东邪西毒,剧情-动作-爱情-武侠-古装
5,霍比特人,动作-奇幻-冒险
-- explode 可以将一组数组的数据变成一列表
select explode(split(types,"-")) from t_movie1;
-- lateral view 表生成函数,可以将explode的数据生成一个列表
select id,name,type from t_movie1,lateral view explode(split(types,"-"))typetable as type;
-- 创建数据库表
create table t_movie2(
id int,
name string,
type string
)
row format delimited fields terminated by ','
lines terminated by '\n';
-- 电影数据 movie2.txt
-- 加载数据到数据库 load data inpath '/yjx/movie2.txt' into table t_movie2;
1,这个杀手不太冷,剧情
1,这个杀手不太冷,动作
1,这个杀手不太冷,犯罪
2,七武士,动作
2,七武士,冒险
2,七武士,剧情
3,勇敢的心,动作
3,勇敢的心,传记
3,勇敢的心,剧情
3,勇敢的心,历史
3,勇敢的心,战争
4,东邪西毒,剧情
4,东邪西毒,动作
4,东邪西毒,爱情
4,东邪西毒,武侠
4,东邪西毒,古装
5,霍比特人,动作
5,霍比特人,奇幻
5,霍比特人,冒险
-- collect_set()和collect_list()都是对列转成行,区别就是list里面可重复而set里面是去重的
-- concat_ws(':',collect_set(type)) ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
select id,concat_ws(':',collect_set(type)) as types from t_movie2 group by id;
-- 聚合格式
select sum(字段名) over([partition by 字段名] [ order by 字段名]) as 别名,
max(字段名) over() as 别名
from 表名;
-- 排序窗口格式
select rank() over([partition by 字段名] [ order by 字段名]) as 别名 from 表名;
测试数据
-- 创建表
create table t_fraction(
name string,
subject string,
score int)
row format delimited fields terminated by ","
lines terminated by '\n';
-- 测试数据 fraction.txt
孙悟空,语文,10
孙悟空,数学,73
孙悟空,英语,15
猪八戒,语文,10
猪八戒,数学,73
猪八戒,英语,11
沙悟净,语文,22
沙悟净,数学,70
沙悟净,英语,31
唐玄奘,语文,21
唐玄奘,数学,81
唐玄奘,英语,23
-- 上传数据
load data inpath '/yjx/fraction.txt' into table t_fraction;
sum(求和)min(最小)max(最大)avg(平均值)count(计数)
--
select name,subject,score,sum(score) over() as sumover from t_fraction;
+-------+----------+--------+----------+
| name | subject | score | sumover |
+-------+----------+--------+----------+
| 唐玄奘 | 英语 | 23 | 321 |
| 唐玄奘 | 数学 | 81 | 321 |
| 唐玄奘 | 语文 | 21 | 321 |
| 沙悟净 | 英语 | 31 | 321 |
| 沙悟净 | 数学 | 12 | 321 |
| 沙悟净 | 语文 | 22 | 321 |
| 猪八戒 | 英语 | 11 | 321 |
| 猪八戒 | 数学 | 73 | 321 |
| 猪八戒 | 语文 | 10 | 321 |
| 孙悟空 | 英语 | 15 | 321 |
| 孙悟空 | 数学 | 12 | 321 |
| 孙悟空 | 语文 | 10 | 321 |
+-------+----------+--------+----------+
select name,subject,score,
sum(score) over() as sum1,
sum(score) over(partition by subject) as sum2,
sum(score) over(partition by subject order by score) as sum3,
-- 由起点到当前行的窗口聚合,和sum3一样
sum(score) over(partition by subject order by score rows between unbounded preceding and current row) as sum4,
-- 当前行和前面一行的窗口聚合
sum(score) over(partition by subject order by score rows between 1 preceding and current row) as sum5,
-- 当前行的前面一行和后面一行的窗口聚合
sum(score) over(partition by subject order by score rows between 1 preceding AND 1 following) as sum6,
-- 当前和后面所有的行
sum(score) over(partition by subject order by score rows between current row and unbounded following) as sum7
from t_fraction;
+-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
| name | subject | score | sum1 | sum2 | sum3 | sum4 | sum5 | sum6 | sum7 |
+-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
| 孙悟空 | 数学 | 12 | 359 | 185 | 12 | 12 | 12 | 31 | 185 |
| 沙悟净 | 数学 | 19 | 359 | 185 | 31 | 31 | 31 | 104 | 173 |
| 猪八戒 | 数学 | 73 | 359 | 185 | 104 | 104 | 92 | 173 | 154 |
| 唐玄奘 | 数学 | 81 | 359 | 185 | 185 | 185 | 154 | 154 | 81 |
| 猪八戒 | 英语 | 11 | 359 | 80 | 11 | 11 | 11 | 26 | 80 |
| 孙悟空 | 英语 | 15 | 359 | 80 | 26 | 26 | 26 | 49 | 69 |
| 唐玄奘 | 英语 | 23 | 359 | 80 | 49 | 49 | 38 | 69 | 54 |
| 沙悟净 | 英语 | 31 | 359 | 80 | 80 | 80 | 54 | 54 | 31 |
| 孙悟空 | 语文 | 10 | 359 | 94 | 10 | 10 | 10 | 31 | 94 |
| 唐玄奘 | 语文 | 21 | 359 | 94 | 31 | 31 | 31 | 53 | 84 |
| 沙悟净 | 语文 | 22 | 359 | 94 | 53 | 53 | 43 | 84 | 63 |
| 猪八戒 | 语文 | 41 | 359 | 94 | 94 | 94 | 63 | 63 | 41 |
+-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
rows必须跟在Order by 子句之后,对排序的结果进行限制,使用固定的行数来限制分区中的数据行数量。
LAG(col,n,default_val):往前第n行数据,col是列名,n是往上的行数,当第n行为null的时候取default_val
LEAD(col,n, default_val):往后第n行数据,col是列名,n是往下的行数,当第n行为null的时候取default_val
NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。
cume_dist(),计算某个窗口或分区中某个值的累积分布。假定升序排序,则使用以下公式确定累积分布:
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) rnp
from t_fraction;
percent_rank() 计算给定行的百分比排名。可以用来计算超过了百分之多少的人
(当前行的rank值-1)/(分组内的总行数-1)
select name,subject,score,
row_number() over(partition by subject order by score) as row_number,
percent_rank() over(partition by subject order by score) as percent_rank
from t_fraction;
官网 https://cwiki.apache.org/confluence/display/Hive/HivePlugins
Hive自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义的UDF来方便的扩展
当Hive提供的内置函数无法满足你的业务处理需要的时候,此时可以考虑使用用户自定义函数
UDF(User-Defined-Function) 单行函数,一进一出
UDAF(User- Defined Aggregation Funcation) 聚集函数,多进一出。
UDTF(User-Defined Table-Generating Functions) 一进多出