Hive 及数据仓库简介

基本概念

Hive 是基于 Hadoop 的一个【数据仓库工具】,可以将结构化的数据文件映射为一张 hive 数据库表,并提供简单的 sql 查询功能,可以将 sql 语句转换为 MapReduce 任务进行运行。

【数据仓库】英文名称为 Data Warehouse,可简写为DW或 DWH。数据仓库,是为企业所有级别的决策制定过程,提供所有类型数据支持的战略集合。它是单个数据存储,出于分析性报告和决策支持目的而创建。为需要业务智能的企业,提供指导业务流程改进、监视时间、成本、质量以及控制。

**Hive 的表其实就是HDFS的目录/文件夹,hive表中的数据 就是hdfs目录中的文件,并按表名把文件夹分开。**如果是分区表,则分区值是子文件夹,可以直接在M/R job里使用这些数据。

Hive 的优缺点

**优点:**使用SQL来快速实现简单的 MapReduce 统计,不必开发专门的 MapReduce 应用,学习成本低,十分适合数据仓库的统计分析。

**缺点:**只适合离线的数据处理,不支持实时查询。

Hive与HBase的关系与区别

关系:

  • Hive与HBase其实没有必然的关系,但是由于HBase的查询语句很不好用,所以可以通过整合Hive,对存储在Hadoop群上的数据提供类SQL的接口进行操作,也就是利用Hive来操作HBase数据库

  • 他们的共同点是数据都存储在HDFS,也就是说他们都是建立于Hadoop之上

区别:

  • 如果你有数据仓库的需求并且你擅长写SQL并且不想写MapReduce jobs就可以用Hive代替。用 HiveQL进行select,join,等等操作。但是Hive只适合做离线的批处理,实时性不高。
  • HBase是一个分布式的NoSql数据库,像其他数据库一样提供随即读写功能。如果你需要实时访问一些数据,就把它存入HBase。你可以用Hadoop作为静态数据仓库,HBase作为数据存储,放那些进行一些操作会改变的数据。

数据处理的分类

1. 联机事务处理OLTP(on-line transaction processing)

OLTP 是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。

OLTP 系统强调数据库内存效率,强调内存各种指标的命令率,强调绑定变量,强调并发操作。

2. 联机分析处理OLAP(On-Line Analytical Processing)

OLAP 是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。

OLAP 系统则强调数据分析,强调 SQL 执行市场,强调磁盘 I/O,强调分区等。

简而言之,数据仓库是用来做查询分析的数据库基本不用来做插入,修改,删除操作。

  • Hive:数据仓库。

  • Hive:解释器,编译器,优化器等。

  • Hive 运行时,元数据存储在关系型数据库里面

  • 编译器将一个Hive SQL转换操作符,操作符是Hive的最小的处理单元

    每个操作符代表HDFS的一个操作或者一道MapReduce作业。

Hive 架构原理

1. 用户接口

用户接口主要有三个:Client CLI、JDBC/ODBC 和 WEBUI。

  • **Client CLI :**Hive shell 命令行,最常用。Client 是 Hive 的客户端,用户连接至 Hive Server。在启动 Client 模式的时候,需要指出 Hive Server 所在节点,并且在该节点启动 Hive Server。

  • **JDBC/ODBC:**Hive的 Java 实现,与传统数据库 JDBC 类似。

  • **WEBUI:**通过浏览器访问 Hive。

2. 元数据存储

Hive 将元数据存储在关系型数据库中,如 mysql、oracle、derby 。 Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

3. 驱动器(Driver)

解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在 HDFS 中,并在随后有 MapReduce调用执行。

4. 数据存储

Hive 的数据存储在 HDFS 中。大部分的查询、计算由 MapReduce 完成(包含 * 的查询,比如 select * from tb 不会生成 MapRedcue 任务)

Hive 搭建及三种模式

Hive 的安装配置

1、安装Hive

安装环境以及前提说明:首先,Hive 是依赖于 hadoop 系统的,因此在运行 Hive 之前需要保证已经搭建好 hadoop 集群环境。

  • 并安装好一个关系型数据:如 mysql

2、配置环境变量

– HADOOP_HOME=/xxx
– HIVE_HOME=/xxx

这里选择配置局部的环境变量,编辑 ~/.bash_profile,具体操作参考我的另一篇文章 Linux常用操作个人整理

3、替换和添加相关jar包

(1) 修改 Hadoop安装包下 /share/hadoop/yarn/lib 目录下的 jline-*.jar

将其替换成 HIVE_HOME/lib 下的 jline-2.12.jar

(2) 将 hive 连接 mysql 的jar包:mysql-connector-java-5.1.32-bin.jar

拷贝到hive解压目录的lib目录下

4、修改配置文件(选择3种模式里的一种)见三种安装模式

5、启动 hive

配置完环境变量,可以在任意客户端的节点上直接输入命令:hive

即可启动。

Hive 配置的三种模式

新建配置文件 hive-site.xml 在 Hive 安装包下的 conf 目录中。

A、内嵌模式(元数据保存在内嵌的derby中,允许一个会话链接,尝试多个会话链接时会报错)【不推荐】

B、本地模式(本地安装mysql 替代derby存储元数据)【推荐】

C、远程模式(远程安装mysql 替代derby存储元数据)【推荐】

1. 内嵌Derby单用户模式

这种安装模式的元数据是内嵌在Derby数据库中的,只能允许一个会话连接,数据会存放到HDFS上。

这种方式是最简单的存储方式,只需要hive-site.xml 做如下配置便可(注:使用 derby 存储方式时,运行 hive 会在当前目录生成一个 derby 文件和一个 metastore_db)。

<!-- 内嵌模式 -->
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:derby:;databaseName=metastore_db;create=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>

2. 本地用户模式

这种安装方式和嵌入式的区别在于:不再使用内嵌的Derby作为元数据的存储介质,而是使用其他数据库比如 MySQL 来存储元数据且是一个多用户的模式,运行多个用户 client 连接到一个数据库中。这种方式一般作为公司内部同时使用 Hive。这里有一个前提,每一个用户必须要有对MySQL的访问权利,即每一个客户端使用者需要知道MySQL的用户名和密码才行。

这种存储方式需要在本地运行一个 mysql 服务器,并作如下配置(下面两种使用 mysql 的方式,需要将 mysql 的 jar 包拷贝到 Hive 安装包下的 lib 目录下。

hive-site.xml 配置如下:

<!-- 1.本地模式 -->
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive_local/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://sean01/hive_remote?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
</configuration>

注意:hive和MySQL不用做HA,单节点就可以。通过设置其他节点可以访问得到数据库。

3. 远程模式

远程模式又分为两种:远程一体和远程分开

(1) 远程一体模式

这种存储方式需要在远端服务器运行一个 mysql 服务器,并且需要在 Hive 服务器启动 meta服务。

<!-- 远程一体模式 -->
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse2</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://sean01:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
</configuration>

注:这里把 hive 的服务端和客户端都放在同一台服务器上了。

(2) 远程分开模式

所谓远程分开模式就是在远程的前提下,把 Hive 的服务端和客户端分开放到两个不同的服务器节点上。

服务端

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://sean01:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
</configuration>

客户端

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://sean02:9083</value> #这里填mysql数据库的服务器地址
</property>
</configuration>

**注意启动:**必须先启动服务端,再启动客户端,否则会报错!

服务端:

hive --service metastore

客户端:直接敲 hive 即可启动

HQL 操作

DDL 语句

Hive 的数据定义语言 ([LanguageManual DDL](javascript:changelink(‘https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL’,'EN2ZH_CN’);))

具体参见:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL

重点是 hive 的建表语句和分区。

创建/删除/修改/使用数据库

1、创建数据库(常用)

CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name [COMMENT database_comment];

如图:创建了一个名叫 sss 的数据库

查看:show databases;

2、删除数据库(不常用)

DROP (DATABASE|SCHEMA) [IF EXISTS] database_name;

删除一个名叫 www 的数据库

3、修改表数据库(不常用)

ALTER (DATABASE|SCHEMA) database_name SET DBPROPERTIES (property_name=property_value, ...);
ALTER (DATABASE|SCHEMA) database_name SET OWNER [USER|ROLE] user_or_role;

4、使用数据库

use database_name;
Use default;

创建、删除表

1、创建表(常用)

(1) 数据类型(data_type)

  • primitive_type 原始数据类型
  • array_type 数组
  • map_type map
  • struct_type
  • union_type – (Note: Available in Hive 0.7.0 and later)

原始数据类型 primitive_type

  • TINYINT

  • SMALLINT

  • INT

  • BIGINT

  • BOOLEAN

  • FLOAT

  • DOUBLE

  • DOUBLE PRECISION

  • STRING 基本可以搞定一切

  • BINARY

  • TIMESTAMP

  • DECIMAL

  • DECIMAL(precision, scale)

  • DATE

  • VARCHAR

  • CHAR

数组(array_type)

  • ARRAY < data_type >

map(map_type)

  • MAP < primitive_type, data_type >

struct_type

  • STRUCT < col_name : data_type [COMMENT col_comment], …>

union_type

  • UNIONTYPE < data_type, data_type, … >

(2) 完整的建表语句

(3) 建表实例:

create table abc(
id int,
name string,
age int,
likes array<string>,
address map<string,string>
)
row format delimited fields terminated by ','
COLLECTION ITEMS TERMINATED by '-'
map keys terminated by ':'
lines terminated by '\n'; #可以不写,默认按换行符

同时在 NameNode 的 HDFS 上也可以看到创建的表路径

(4) 导入数据(属于DML但是为了演示需要在此应用):

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

数据如下:

1,zshang,18,game-girl-book,stu_addr:beijing-work_addr:shanghai
2,lishi,16,shop-boy-book,stu_addr:hunan-work_addr:shanghai
3,wang2mazi,20,fangniu-eat,stu_addr:shanghai-work_addr:tianjing
4,wxiaokun,18,fangniu-book-game,stu_addr:wuhan-work_addr:nanjing
5,xshufan,20,boy-girl-book,stu_addr:tokyo-work_addr:hangzhou

首先在本地新建一个文件来装这些数据 :vim hivedata

然后加载到 abc 这张表中

load data local inpath '/root/hivedata' overwrite into table abc;

注意:如果不加 local 加载的就不是本地,是加载 HDFS 上的文件

在之前的版本,需要在路径中写全 hdfs 的路径(加上集群的名称),现在新的版本已经优化了,不加 local 就是在 hdfs 上找,加了就会到本地服务器上找。

load data inpath 'hdfs://Xss/hivedata' overwrite into table abc;

2、删除表

(1) 使用 Hive 删除表

DROP TABLE [IF EXISTS] table_name [PURGE];

比如删除刚刚创建的表 abc

(2) 使用 hdfs 删除表

因为 Hive 的元数据信息存储在 mysql 上,而数据存储在 HDFS 上,所以如果用 hdfs 的命令来删除表,会删除表里的数据,并不能删除元数据信息。

试验一下:我们用 hdfs 删除 abc 里的数据,然后重新把数据加载回来

hdfs dfs -rm -r /user/hive_local/warehouse/sss.db/abc/hivedata

删除之后 hive 中就无法查找到结果

使用 hdfs 把数据 put 回来

hdfs dfs -put hivedata /user/hive_local/warehouse/sss.db/abc

再次查看时,数据重新回来!

注意区别:

1、HDFS 删除的是表里的数据,不会删除表的元数据信息;

2、Hive删除普通表会把数据连带元数据信息一并删除;

3、Hive删除外部表只会删除元数据信息,不会删除数据。

因为 HDFS 删除和 Hive 删除普通表直接会删除数据,数据很重要,所以慎用!!!

使用 hive 删除普通表就会连带表的元数据信息彻底的删除。所以为了防止使用 hive 时避免误删,我们引入外部表来控制 hive 删除表的操作。

3、外部表

外部关键字 EXTERNAL 允许您创建一个表,并提供一个位置,以便 hive 不使用这个表的默认位置。这方便如果你已经生成的数据。当删除一个外部表,表中的数据不是从文件系统中删除。外部表指向任何 HDFS 的存储位置,而不是存储在配置属性指定的文件夹 hive.metastore.warehouse.dir 中。

开始创建外部表,需要在create 前加上关键字 external

create external table person(
id int,
name string,
age int,
likes array<string>,
address map<string,string>
)
row format delimited fields terminated by ','
COLLECTION ITEMS TERMINATED by '-'
map keys terminated by ':';

加载数据

load data local inpath '/root/hivedata' overwrite into table abc;

然后使用 hive 删除表 abc

查询 mysql 数据库,发现元数据信息已经没有了

再看 HDFS 中,数据却还在

因为数据还在,于是只需要重新创建一下这个表就可以了

修改、更新表,删除表数据

这些一般工作中很少用

  • 重命名表
ALTER TABLE table_name RENAME TO new_table_name;
Eg: alter table meninem rename to sean;
  • 更新数据
UPDATE table_name SET column = value [, column = value ...] [WHERE expression]
  • 删除表数据
DELETE FROM table_name [WHERE expression]  # 需要配置权限

DML 语句

Hive数据操作语言([LanguageManual DML](javascript:changelink(‘https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML’,'EN2ZH_CN’);))

具体参见:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML

重点是数据加载和查询插入语法

四种插入/导入数据

Hive 不能很好的支持用 insert 语句一条一条的进行插入操作,不支持 update 。数据是以 load 的方式加载到建立好的表中。数据一旦导入就不可以修改。

注意区分:在load数据时使用的是[overwrite] into,但是插入数据时是insert overwrite/into

第一种

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] 
INTO TABLE table_name

第二种

INSERT OVERWRITE TABLE person
   SELECT id,name,age,likes,address From abc;

先创建一个 person 表

create external table person(
id int,
name string,
age int,
likes array<string>,
address map<string,string>
)
row format delimited fields terminated by ','
COLLECTION ITEMS TERMINATED by '-'
map keys terminated by ':';

再把 abc 表里的数据插入到 person 表中

第三种

FROM person t1
INSERT OVERWRITE TABLE person2
       SELECT t1.id, t1.name, t1.age ;

先创建 person2 这个表

create table person2(
id int,
name string,
age int
)
row format delimited fields terminated by ',';

再插入 person 表中所需的三个字段的数据,得到数据。

【from放前面好处就是后面可以插入多条语句 】

第四种

拓展:本地load数据和从HDFS上load数据的过程有什么区别?

本地: load 会自动复制到 HDFS 上的 hive 的 ** 目录下

HDFS:load 会移动数据到 HDFS 上的 hive 的 ** 目录下,原来的就没有了。

查询数据并保存

举例:我们用 person2 这张表作为查询对象

先查看一下 person2 表的数据信息

A、保存数据到本地

将 person2 表的查询信息保存到本地目录的 /root/hive_exp 下

insert overwrite local directory '/root/hive_exp'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' #以','隔开
select * from person2;

然后查看本地

B、保存到 HDFS 上

将 person2 表的查询信息保存到 HDFS 目录的 /user/hive/hive_exp下

insert overwrite directory '/user/hive/hive_exp'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' #以','隔开
select * from person2;

然后查看 HDFS

C、在外部 shell 中将数据重定向到文件中

有时我们在外部想利用 sql 查询表数据信息,但是又不想进到 hive 里面去,就可以用到外部 shell 的操作

比如:把 abc 这张表的数据标准输出重定向到本地 root 目录下的 abc.txt 文件中

hive -e "select * from sss.abc;" > /root/abc.txt	#注意表明前一定要带上数据库的名称,否则会找不到而报错!

备份数据或还原数据

1、备份数据

备份使用关键字export

举例:将person2表中的数据备份到 HDFS 中的目录 /user/hadoop/hive/datas 下

EXPORT TABLE person2 TO '/user/hadoop/hive/datas';

2、删除再还原数据

先删除表

drop table person2;

再还原数据

IMPORT FROM '/user/hadoop/hive/datas';

Hive SerDe

Hive SerDe(Serializer and Deserializer),SerDe 用于做序列化和反序列化。

构建在数据存储和执行引擎之间,对两者实现解耦。

Hive 通过 ROW FORMAT DELIMITED 以及 SERDE 进行内容的读写。

1、格式:

row_format
: DELIMITED
[FIELDS TERMINATED BY char [ESCAPED 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, ...)]

2、举例:处理一些请求数据,对数据做固定格式的清洗

表数据文件:localhost_access_log.2016-02-29.txt

192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-upper.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-nav.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /asf-logo.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-button.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-middle.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET / HTTP/1.1" 200 11217
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET / HTTP/1.1" 200 11217
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /asf-logo.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-middle.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-button.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-nav.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-upper.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET / HTTP/1.1" 200 11217
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET / HTTP/1.1" 200 11217
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /tomcat.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-button.png HTTP/1.1" 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET /bg-upper.png HTTP/1.1" 304 -

创建表

Hive 正则匹配(去掉中括号和 “ ” 号)

CREATE TABLE logtbl (
host STRING,
identity STRING, //身份
t_user STRING,
time STRING,
request STRING,
referer STRING, //来路
agent STRING) //代理
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' //继承类
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)"
) //正则
STORED AS TEXTFILE; //存储为text文件

把数据文件上传数据到服务器,然后加载到表中

load data local inpath '/root/localhost_access_log.2016-02-29.txt' into table logtbl;

Beeline 和 Hiveser2

Hiveserver2 是 Hive server的第二个版本。

1、Hiveserver2 启动。

在服务端直接使用命令 hiveserver2 即可

Beeline 是 在 Hive 里的,他在 Hive 安装包下的 bin 目录下

2、启动 Beeline。

所以只要有 Hive 就能启动 Beeline,无论是分开模式还是一体模式。

3、Beeline 连接 hiveserver2

!connect jdbc:hive2://sean01:10000 root 123456  #连接mysql数据库

4、使用 Beeline 查询

查看效果:会发现 Beeline 在格式上进行了美化,也算是优化

1547367862685

注意:在实际工作中,Beeline并不怎么用,因为非常格式上要进行切分,非常消耗资源。

Hive 的 JDBC

一般是平台使用展示或接口,服务端启动hiveserver2后,在java代码中通过调用hive的jdbc访问默认端口10000进行连接、访问。(这种格式使用的比较少)

Hive 分区与自定义函数

Hive 的分区(partiton)

假如现在我们公司一天产生3亿的数据量,那么为了方便管理和查询,此时可以建立分区(可按日期 部门等具体业务分区)。分门别类的管理。

注意:必须在表定义时创建 partition !

分区分为:单分区和多分区

分区分为:静态分区和动态分区

创建分区

A、单分区建表语句

create table day_table(id int, content string) 
partitioned by (dt string)
row format delimited fields terminated by ',';

【单分区表,按天分区,在表结构中存在id,content,dt三列;以dt为文件夹区分】

新建数据文件 hivedata2 在本地 root 下

加载数据到分区表中

load data local inpath '/root/hivedata2' into table day_table partition(dt='2008-08-08');

查看表信息

查看表结构(使用关键字 desc)

查看 HDFS

注意:在 HDFS 中不能用‘/’和‘-’连接字段,否则会乱码。

B、双分区建表语句

create table day_hour_table (id int, content string) 
partitioned by (dt string, hour string)
row format delimited fields terminated by ',';

【双分区表,按天和小时分区,在表结构中新增加了dt和hour两列;先以dt为文件夹,再以hour子文件夹区分】

加载数据到双分区表中

load data local inpath '/root/hivedata2' into table day_hour_table partition(dt='2008-08-08',hour='01-02');

查看表信息

查看 HDFS

注意:在创建 删除多分区等操作时一定要注意分区的先后顺序,他们是父子节点的关系。分区字段不要和表字段相同

添加分区表的分区字段

表分区已创建,在此基础上添加具体分区。

比如在建表的时候就已经定义了分区:partitioned by(dt string),我们可以根据这个类型新建多个分区字段,比如按天去分区,每天就是一个文件夹。

语法格式

ALTER TABLE table_name
ADD partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...

alter table day_table add partition(dt='2008-08-08');
alter table day_table add partition(dt='2008-08-09');
alter table day_table add partition(dt='2008-08-10');

添加的前提是表在创建时已经定义了相应的分区。比如:添加一个单分区字段,前提是在创建这张表时已经定义了这个单分区,多分区同理。

删除分区

语法格式

ALTER TABLE table_name DROP partition_spec, partition_spec,...

用户可以用 ALTER TABLE DROP PARTITION 来删除分区。分区的元数据和数据将被一并删除。

alter table day_hour_table drop partition(dt='2008-08-08');

数据加载进分区表中

语法格式

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1,partcol2=val2 ...)]

例如

load data local inpath '/root/hivedata2' into table day_table partition(dt='2008-08-08');

当数据被加载至表中时,不会对数据进行任何转换,Load操作只是将数据复制至Hive表对应的位置

数据加载时在表下自动创建一个目录基于分区的查询的语句:

select * from day_table where day_table.dt >= '2008-08-08'

查看分区语句

例如:

hive> show partitions day_hour_table;

重命名分区

语法格式

ALTER TABLE table_name PARTITION partition_spec RENAME TO PARTITION partition_spec;

例如

alter table day_table partition (tian='2018-05-01') rename to partition (tain='2018-06-01');

动态分区

1、创建数据

在本地文件 /root/hivedata3 中写入以下4行数据

aaa,US,CA
aaa,US,CB
bbb,CA,BB
bbb,CA,BC

2、建立非分区表并加载数据

创建表 t1

CREATE TABLE t1 (name STRING, cty STRING, st STRING) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

加载数据 hivedata3

LOAD DATA LOCAL INPATH '/root/hivedata3' INTO TABLE t1;

查询 t1

3、创建外部分区表(普通分区表也可以)

CREATE EXTERNAL TABLE t2 (name STRING) PARTITIONED BY (country STRING, state STRING);

这时就需要使用动态分区来实现。

使用动态分区需要注意设定以下参数:

- hive.exec.dynamic.partition
默认值:true
是否开启动态分区功能,默认true开启。
使用动态分区时候,该参数必须设置成true;

- hive.exec.dynamic.partition.mode
默认值:strict
动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。
一般需要设置为nonstrict

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

- hive.exec.max.dynamic.partitions
默认值:1000
在所有执行MR的节点上,最大一共可以创建多少个动态分区。
同上参数解释。

- hive.exec.max.created.files
默认值:100000
整个MR Job中,最大可以创建多少个HDFS文件。
一般默认值足够了,除非你的数据量非常大,需要创建的文件数大于100000,可根据实际情况加以调整。

- hive.error.on.empty.partition
默认值:false
当有空分区生成时,是否抛出异常。
一般不需要设置。

比如设定 当前动态分区的模式为非严格模式 nonstrict

4、插入数据

将 t1 表的数据动态插入到 t2 表中

INSERT INTO TABLE t2 PARTITION (country, state) SELECT name, cty, st FROM t1;

查询 t2

自定义函数

常用函数无法满足日常需求,比如脱敏:去掉敏感数据

自定义函数包括三种:UDF、UDAF、UDTF

  • UDF:一进一出

  • UDAF:聚集函数,多进一出。如:Count/max/min

  • UDTF:一进多出,如 lateralview 侧视图 explore()

使用方式 :在HIVE 会话中 add 自定义函数的 jar 文件,然后创建 function 继而使用函数。

UDF 开发(常用)

1、UDF 函数可以直接应用于 select 语句,对查询结构做格式化处理后,再输出内容。

2、编写 UDF 函数的时候需要注意一下几点:

​ a)自定义 UDF 需要继承类 org.apache.hadoop.hive.ql.UDF。

​ b)需要实现 evaluate 函数,evaluate 函数支持重载。

​ 源码:

package com.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class TuoMin extends UDF{
private Text res = new Text();
public Text evaluate(String str){
if (str == null) {
return null;
}
// 1***0
String first = str.substring(0, 1);
String last = str.substring(str.length()-1, str.length());
res.set(first + "***" + last);
return res;
}
}

3、步骤

​ a)把程序打包放到目标机器上去;

b)进入 hive 客户端,添加 jar 包:

​ 因为 jar 包添加到环境变量中,所以不用的时候要删除

hive > add jar /root/TuoMin.jar;
(清除缓存时记得删除jar包 delete jar /root/TuoMin.jar;)

​ c)创建临时函数:

hive > create temporary function tuomin as 'com.hive.udf.TuoMin';

​ d)查询 HQL 语句:

​ 使用自定义函数 tuomin 来查询表 abc 的 name 字段

​ 表 abc 原数据

​ 进行脱敏

select tuomin(name) from abc;

​ e)销毁临时函数:

hive > drop temporary function tuomin;

UDAF 自定义集函数(不用)

多行进一行出,如 sum()、min(),用在 group by 时

1、必须继承org.apache.hadoop.hive.ql.exec.UDAF(函数类继承)

​ org.apache.hadoop.hive.ql.exec.UDAFEvaluator(内部类 Eval uator 实现 UDAFEvaluator 接口)

2、Evaluator 需要实现 init、iterate、terminatePartial、merge、t erminate 这几个函数

  • init():类似于构造函数,用于 UDAF 的初始化
  • iterate():接收传入的参数,并进行内部的轮转,返回 boolean
  • terminatePartial():无参数,其为 iterate 函数轮转结束后,返回轮转数据,类似于 hadoop 的 Combinermerge(),用于接收 terminatePartial 的返回结果,进行数据 merge 操作,其返回类型为 boolean
  • terminate():返回最终的聚集函数结果

UDTF (不常用)

一进多出,如 lateral view explode()

案例实战

基站掉话率

1、创建原始表

create table cell_monitor(
record_time string,
imei string,
cell string,
ph_num int,
call_num int,
drop_num int,
duration int,
drop_rate DOUBLE,
net_type string,
erl string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

2、结果表

create table cell_drop_monitor(
imei string,
total_call_num int,
total_drop_num int,
d_rate DOUBLE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;

3、加载原始数据

LOAD DATA LOCAL INPATH '/root/cdr_summ_imei_cell_info.csv' OVERWRITE INTO TABLE cell_monitor;

4、找出掉线率最高的基站

from cell_monitor cm 
insert overwrite table cell_drop_monitor
select cm.imei ,sum(cm.drop_num),sum(cm.duration),sum(cm.drop_num)/sum(cm.duration) d_rate
group by cm.imei
sort by d_rate desc;

5、查询结果表

比如查询前十条数据

select * from cell_drop_monitor limit 10;

WC 单词统计

案例:做一个单词统计

例如:新建一个叫 wc 的文件

1、建表

create table docs(line string);  #原表
create table wc(word string, totalword int); #统计结果表

2、加载原始数据

load data local inpath '/root/wc' into table docs;

3、统计

from (select explode(split(line, ' ')) as word from docs) w 
insert into table wc
select word, count(1) as totalword
group by word
order by word;

4、查询结果

select * from wc;

分桶

分桶表及应用场景

分桶表是对列值取哈希值求余的方式,将不同数据放到不同文件中存储。

对于hive中每一个表、分区都可以进一步进行分桶。由列的哈希值除以桶的个数来决定每条数据划分在哪个桶中。

适用场景:

数据抽样( sampling )、map-join

开启支持分桶

set hive.enforce.bucketing=true;

默认:false;设置为 true 之后,mr 运行时会根据bucket的个数自动分配 reduce task 个数。(用户也可以通过mapred.reduce.tasks 自己设置 reduce 任务个数,但分桶时不推荐使用)

注意:一次作业产生的桶(文件数量)和 reduce task 个数一致。

往分桶表中加载数据

insert into table bucket_table select columns from tbl;
insert overwrite table bucket_table select columns from tbl; #二者选其一

桶表 抽样查询

select * from bucket_table tablesample(bucket 1 out of 4 on columns); #抽样函数

tablesample 语法:

tablesample(bucket x out of y)

x:表示从哪个bucket开始抽取数据

y:必须为该表总bucket数的倍数或因子

1、创建普通表

例:

CREATE TABLE mm( id INT, name STRING, age INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

测试数据:

1,tom,11
2,cat,22
3,dog,33
4,hive,44
5,hbase,55
6,mr,66
7,alice,77
8,scala,88

在本地 root 下创建一个 hivedata4 的文件

2、创建分桶表

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

3、加载数据到普通表

load data local inpath '/root/hivedata4' into table mm;

4、插入数据到分桶表中

insert into table psnbucket select id, name, age from mm;

5、抽样

select id, name, age from psnbucket tablesample(bucket 1 out of 4 on age);
select id, name, age from psnbucket tablesample(bucket 2 out of 4 on age);
select id, name, age from psnbucket tablesample(bucket 3 out of 4 on age);
select id, name, age from psnbucket tablesample(bucket 4 out of 4 on age);

从第一个桶开始抽一直到第四个

总结:我们互发现,在分桶抽样中,抽取数据会尽量分散去取

分析图:

Hive Lateral View(视图)

Lateral View 用于和 UDTF 函数(explode、split)结合来使用。

首先通过 UDTF 函数把一个语句拆分成多行,然后通过 Lateral View 将多行结果组合成一个支持别名的虚拟表,也就是合并为一个字段。

主要解决在select使用UDTF做查询过程中,查询只能包含单个UDTF,不能包含其他字段、以及多个UDTF的问题。

简单说:UDTF 先一进多出,Lateral View 拿到多条数据后多进一出。

语法:

lateral view udtf(expression) tableAlias as columnAlias (',' columnAlias)

例:

统计人员表中共有多少种爱好、多少个城市?

数据来自表 abc

HQL语句:

select count(distinct(myCol1)), count(distinct(myCol2))) from abc 
lateral view explode(likes) myTable1 as myCol1
lateral view explode(address) myTable2 as myCol2, myCol3; #切记。虽然myCol3没用到,但是这里不能删,否则会因为数据个数不匹配报错,因为数据中有两种地址:学习地址和工作地址。

显示结果:一共7种爱好、2个学习地址。

运行方式

**1、命令行方式 Cli:**控制台模式

  • 与 hdfs 交互

    执行 dfs 命令:例如 dfs -ls /

  • 与 Linux 交互

    ! 开头:例如 !pwd

**2、脚本运行方式:**实际生产环境中使用最多

  • hive -e " SQL 语句 "

  • hive -e " " > aaa

  • hive -S -e “” > aaa -S意思是静默模式,不打印 log 日志信息

  • hive -f file(file里可以放很多SQL语句)

  • hive -i /home/my/hive-init.sql

  • hive > source file (在 hive cli 中运行)

3、JDBC 方式

hiveserver2

4、Web GUI 接口

hwi、hue等

Hive Web GUI接口

web界面安装:

1、下载源码包apache-hive-*-src.tar.gz

2、将hwi war包放在$HIVE_HOME/lib/

制作方法:将hwi/web/*里面所有的文件打成war包

cd apache-hive-1.2.1-src/hwi/web jar -cvf hive-hwi.war *

3、复制tools.jar(在jdk的lib目录下)到$HIVE_HOME/lib下

4、修改hive-site.xml

<property>
<name>hive.hwi.listen.host</name>
<value>0.0.0.0</value>
</property>
<property>
<name>hive.hwi.listen.port</name>
<value>9999</value>
</property>
<property>
<name>hive.hwi.war.file</name>
<value>lib/hive-hwi.war</value>
</property>

5、启动hwi服务(端口号9999)

hive --service hwi

6、浏览器通过以下链接来访问

http://sean03:9999/hwi/

Hive参数与变量

Hive当中的参数、变量

hive当中的参数、变量,都是以命名空间开头

通过${}方式进行引用,其中system、env下的变量必须以前缀开头。

Hive 参数设置方式

1、修改配置文件 ${HIVE_HOME}/conf/hive-site.xml

2、启动hive cli时,通过–hiveconf key=value的方式进行设置

​ 例:hive --hiveconf hive.cli.print.header=true

3、进入cli之后,通过使用set命令设置

Hive set命令

在 hive CLI 控制台可以通过set对hive中的参数进行查询、设置。

  • set 设置:

    set hive.cli.print.header=true;
  • set 查看:

    set hive.cli.print.header
  • hive参数初始化配置

    当前用户家目录下的.hiverc文件,如: ~/.hiverc

    如果没有,可直接创建该文件,将需要设置的参数写到该文件中,hive启动运行时,会加载改文件中的配置。

  • hive历史操作命令集

    ~/.hivehistory

权限管理

权限类别

1、Storage Based Authorization in the Metastore Server基于存储的授权

可以对Metastore中的元数据进行保护,但是没有提供更加细粒度的访问控制(例如:列级别、行级别)。

2、Default Hive Authorization (Legacy Mode) hive默认授权

设计目的仅仅只是为了防止用户产生误操作,而不是防止恶意用户访问未经授权的数据。

3、SQL Standards Based Authorization in HiveServer2基于SQL标准的Hive授权

完全兼容SQL的授权模型,推荐使用该模式。

基于SQL标准Hive授权模型,除支持对于用户的授权认证,还支持角色role的授权认证,role可理解为是一组权限的集合,通过role为用户授权。一个用户可以具有一个或多个角色,默认包含俩种角色:public、admin

授权限制

1、启用当前认证方式之后,dfs, add, delete, compile, and reset等命令被禁用。

2、通过set命令设置hive configuration的方式被限制某些用户使用。

(可通过修改配置文件hive-site.xml中hive.security.authorization.sqlstd.confwhitelist进行配置)

3、添加、删除函数以及宏(批量规模)的操作,仅为具有admin的用户开放。

4、用户自定义函数(开放支持永久的自定义函数),可通过具有admin角色的用户创建,其他用户都可以使用。

5、Transform功能被禁用

在 hive 服务端修改配置文件 hive-site.xml 添加以下配置内容:

<property>
<name>hive.security.authorization.enabled</name>
<value>true</value> //开启用户权限认证
</property>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value> //默认true,设为false查询将以运行hiveserver2进程的用户运行
</property>
<property>
<name>hive.users.in.admin.role</name>
<value>root</value> //超级管理员角色用户
</property>
<property>
<name>hive.security.authorization.manager</name>
<value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value>
</property>
<property>
<name>hive.security.authenticator.manager</name>
<value>org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator</value>
</property>

服务端启动hiveserver2;客户端通过beeline进行连接

角色的添加、删除、查看、设置:

CREATE ROLE role_name; – 创建角色

DROP ROLE role_name; – 删除角色

SET ROLE (role_name|ALL|NONE); – 设置角色

SHOW CURRENT ROLES; – 查看当前具有的角色

SHOW ROLES; – 查看所有存在的角色

思考总结

1、Hive中的自定义函数的jar包放置

Hive自定义的函数jar包最好放置到分布式存储系统HDFS上,这样可以有效的防止当前节点服务器发生意外宕机,jar 包丢失。