Hive学习详细版

一.概述

1.Hadoop的开发问题

只能用java语言开发,存在语言门槛
需要对Hadoop底层原理,api比较了解才能做开发
开发调试比较麻烦

2.什么是Hive

Hive是基于Hadoop的一个数据仓库工具。可以将结构化的数据文件映射为一张表,并提供完整的sql查询功能
底层是将sql语句转换为MapReduce任务进行运行
Hive提供了一系列的工具,可以用来进行数据提取、转化、加载(ETL Extract-Transform-Load ),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制
本质上是一种大数据离线分析工具

3.HQL

HQL - Hive通过类SQL的语法,来进行分布式的计算
HQL用起来和SQL非常的类似,Hive在执行的过程中会将HQL转换为MapReduce去执行,所以Hive其实是基于Hadoop的一种分布式计算框架,底层仍然是MapReduce

4.优点和缺点

优点:

学习成本低,只要会sql就能用hive
开发效率高,不需要编程,只需要写sql
模型简单,易于理解
针对海量数据的高性能查询和分析
HiveQL 灵活的可扩展性(Extendibility)
高扩展性(Scalability)和容错性
与 Hadoop 其他产品完全兼容

缺点:

不支持行级别的增删改
不支持完整的在线事务处理
本质上仍然是MR的执行,效率不算高

5.适用场景

Hive 构建在基于静态(离线)批处理的Hadoop 之上,Hadoop 通常都有较高的延迟并且在作业提交和调度的时候需要大量的开销。因此,Hive 并不能够在大规模数据集上实现低延迟快速的查询因此,Hive 并不适合那些需要低延迟的应用
Hive 并不提供实时的查询和基于行级的数据更新操作,最佳使用场合是大数据集的离线批处理作业,例如,网络日志分析

二.执行流程

1.通过客户端提交一条Hql语句
2.通过complier(编译组件)对Hql进行词法分析、语法分析。在这一步,编译器要知道此hql语句到底要操作哪张表
3.去元数据库找表信息
4.得到信息
5.complier编译器提交Hql语句分析方案
6.执行流程
  a.executor 执行器收到方案后,执行方案(DDL过程)。在这里注意,执行器在执行方案时,会进行判断:如果当前方案不涉及到MR组件,比如为表添加分区信息、比如字符串操作等,比如简单的查询操作等,此时就会直接和元数据库交互,然后去HDFS上去找具体数据;如果方案需要转换成MR job,则会将job 提交给Hadoop的JobTracker
  b.MR job完成,并且将运行结果写入到HDFS上
  c.执行器和HDFS交互,获取结果文件信息
7.如果客户端提交Hql语句是带有查询结果性的,则会发生:7-8-9步,完成结果的查询

三.优化(略)

1. map side join
2.join语句优化
3.group by 优化
4.count distinct 优化
5.调整切片数(map任务数)
6.JVM重利用
7.启用严格模式
8.关闭推测执行机制

四.安装

伪分布式下安装Hive

1.安装JDK

cd /opt/software
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.tar.gz
tar -xvf
jdk-8u201-linux-x64.tar.gz

2.安装Hadoop

wget http://mirrors.shu.edu.cn/apache/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz
tar -xvf hadoop-2.7.1.tar.gz

4.配置JDK和Hadoop的环境变量

vim /etc/profile

#JAVA_HOME
export JAVA_HOME=/opt/software/jdk-8u201-linux-x64
export PATH=$PATH:$JAVA_HOME/bin

#HADOOP_HOME
export HADOOP_HOME=/opt/software/hadoop-2.7.1
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

#保存退出后
source /etc/profile

5.下载解压Hive安装包

wget http://mirrors.shu.edu.cn/apache/apache-hive-1.2.0-bin.tar.gz
tar -xvf apache-hive-1.2.0-bin.tar.gz

6.启动Hadoop的HDFS和Yarn

start-all.sh

7.进入到Hive的bin目录,启动Hive:sh hive (或者执行:./hive)

cd /opt/software/apache-hive-1.2.0-bin/bin
sh hive

配置MySQL

1.下载mysql安装包
2.确认当前虚拟机之前是否有安装过mysql

rpm -qa #查看linux安装过的所有rpm包
rpm -qa | grep mysql

删除mysql

rpm -ev --nodeps mysql-libs-5.1.71-1.el6.x86_64

再执行:

rpm -qa | grep mysql #发现没有相关信息

3.安装mysql server rpm包和client包

rpm -ivh MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm
rpm -ivh MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm

4.修改my.cnf,默认在/usr/my.cnf,执行:vim /usr/my.cnf,添加如下内容

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

5.将mysqld加入系统服务,并随机启动

cp /usr/share/mysql/mysql.server /etc/init.d/mysqld

6.启动mysqld,执行:

service mysqld start

7.查看初始生成的密码,执行:

vim /root/.mysql_secret

这个密码随机生成的
8.修改初始密码

mysqladmin -u root -p password root

此时,提示要输入初始生成的密码,拷贝过来即可
9.进入mysql数据库

mysql -u root -p

如果出现不能修改密码的问题,则可以执行如下命令强制修改:
a.关闭MySQL服务:

service mysqld stop

b.进入安全模式:

mysqld_safe --user=mysql --skip-grant-tables --skip-networking &

c.在安全模式下输入:

mysql -u root mysql

d.进入mysql之后输入:

UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
FLUSH PRIVILEGES;
quit;

e.重启MySQL服务:

service mysqld restart

五.基础操作

show databases; #查数据库
create database park; #创建park数据库
use park; #进入park数据库
show tables; 查看表
create table stu (id int,name string); #创建stu表
create table stu2 like stu; #创建一个和表stu结构一样的stu2表
insert into stu values(1,'zhang'); #向表stu插入数据
select * from stu; #查看表stu数据
desc stu; #查看表stu结构
drop table stu; #删除表stu
create table stu(id int,name string) row format delimited fields terminated by ' '; #创建stu表,并指定分割符 空格
load data local inpath '/opt/software/1.txt' into table stu; #通过加载文件数据到指定的表stu里
insert overwrite table stu1 select * from stu; #把stu表数据插入到stu1表中
insert overwrite local directory '/opt/stu' row format delimited fields terminated by ' ' select * from stu; #将stu表中查询的数据写到本地的/opt/stu目录下
insert overwrite directory '/stu' row format delimited fields terminated by ' ' select * from stu; #将stu表中查询的数据写到HDFS的stu目录下
from stu insert overwrite table stu1 select * insert overwrite table stu2 select *; #将stu表中查询的数据写到stu1以及stu2两张表中
alter table stu rename to stu2; #为表stu重命名为stu2
alter table stu add columns (age int); #为表stu增加一个列字段age,类型为int
exit; #退出Hive

注意点:
1.创建的数据库,实际是在Hadoop的HDFS文件系统里创建一个目录节点,统一存在: /user/hive/warehouse 目录下
2.hive里,表示字符串用的是string,不用char和varchar
3.所创建的表,也是HDFS里的一个目录节点
4.HDFS不支持数据的修改和删除,因此已经插入的数据不能够再进行任何的改动
5.insert into 语句执行的实际上是追加操作
6.Hive支持查询,行级别的插入。不支持行级别的删除和修改
7.Hive的操作实际是执行一个job任务,调用的是Hadoop的MR
8.插入完数据之后,发现HDFS stu目录节点下多了一个文件,文件里存了插入的数据,因此,hive存储的数据,是通过HDFS的文件来存储的
9.Hive的工作原理实际上就是在管理hdfs上的文件,把文件里数据抽象成二维表结构,然后提供hql语句供程序员查询文件数据
10.like只复制表结构,不复制数据

六.表结构

1.内部表和外部表

a.内部表和外部表概述
内部表:先在hive里建一张表,然后向这个表插入数据(用insert可以插入数据,也可以通过加载外部文件方式来插入数据),这样的表称之为hive的内部表
外部表:HDFS里已经有数据了,然后,通过hive创建一张表来管理这个文件数据。则这样表称之为外部表。需要注意的是,hive外部表管理的是HDFS里的某一个目录下的文件数据
外部表创建命令:

create external table stu (id int,name string) row format delimited fields terminated by ' ' location '/目录路径';

b.内部表和外部表区别
对于内部表,在删除该表的时候,HDFS对应的目录节点会被删除
对于外部表,在删除该表的时候,HDFS对应的目录节点不会删除

2.分区表

a.分区表概述
分区表可以通过添加指定的字段来提高Hive的查询效率
在数据量较大的情况下,往往会添加分区表来避免全表查询
b.指令
#创建book表,以category作为分区(在创建分区表时,partitioned字段可以不在字段列表中。生成的表中自动就会具有该字段)

create table book (id int, name string) partitioned by (category string) row format delimited fields terminated by '\t';

#将本地文件cn.txt添加到book表中,分区字段为cn(在HDFS下会生成category=cn目录)

load data local inpath '/home/cn.txt' overwrite into table book partition (category='cn');

#查看分区为cn的数据

select * from book where category='cn';

#将指定的目录添加为分区字段

ALTER TABLE book add PARTITION (category = 'jp') location '/user/hive/warehouse/park.db/book/category=jp';

#查看分区

show partitions iteblog;

#修复分区

msck repair table book;

#删除分区

alter table book drop partition(category='cn');

#修改分区的名字

alter table book partition(category='french') rename to partition (category='hh');

c.动态分区
如果在进行查询的时候一个表中的数据是未分区的一个表中的数据是已经分区的,则此时从未分区的表中查询数据向已分区表中添加是不行的。所以此时需要开启动态分区
设置指令:

set hive.exec.dynamic.partition = true;
set hive.exec.dynamic.partition.mode = nostrict;
insert into table stu2 partition(class) select id, name, class from stu distribute by class;

3.分桶表

a.分桶表概述
分桶表是一种更细粒度的数据分配方式
一个表既可以分区也可以分桶
分桶的主要作用是实现数据的抽样,方便进行数据测试
分桶表通过hash分桶算法,将数据分放在不同的桶(hdfs中的文件)中,方便后续获取
分桶表机制默认是不开启的,需要手动开启:set hive.enforce.bucketing=true;
分桶表不允许以外部文件方式导入数据,只能从另外一张表数据导入
操作指令:
#创建teacher表,以name作为分桶机制,分为3个桶

create table teacher(name string) clustered by (name) into 3 buckets row format delimited fields terminated by ' ';

#将tmp表中的数据添加到teacher表中(实际上是产生了3个文件用于存储不分桶的数据)

insert overwrite table teacher select * from tmp;

#进行抽样

select * from teacher tablesample(bucket 1 out of 3 on name);

抽样格式为:bucket x out of y on XXX
1. x表示抽样的起始桶,例如bucket 1 out of 3表示从第1 个桶开始抽取数据
2. y决定抽样的比例,要求必须是桶数的因子或者整数倍
a. 如果桶数为6,y为2,则表示抽取6/2=3个桶中的数据
b. 如果桶数为6,y为3,则表示抽取6/3=2个桶中的数据
c. 如果桶数为6,y为12,则表示抽取6/12=0.5个桶中的数据

如果桶数为6,抽样为bucket 1 out of 3 on id表示从第1个桶开始抽样,抽取2个桶的数据,所以抽取的样本为1和4桶中的数据

七.Hive中的join

#建表

create external table order_t (id string,time string,pid string,amount int) row format delimited fields terminated by ' ' location '/order';
create external table product_t (pid string,name string,price int) row format delimited fields terminated by ' ' location '/product';

#join查询

select * from product_t join order_t on product_t.pid=order_t.pid;

#inner join

select * from product_t inner join order_t on product_t.pid=order_t.pid;

#left join

select * from product_t left join order_t on product_t.pid=order_t.pid;

#right join

select * from product_t right join order_t on product_t.pid=order_t.pid;

#full outer join

select * from product_t full outer join order_t on product_t.pid=order_t.pid;

#left semi join

select * from product_t left semi join order_t on product_t.pid=order_t.pid;

八.其他注意点

1.SerDe序列化

概述:
SerDe是Hive提供用于进行序列化和反序列化的机制
其中提供了正则表达式形式用以读取不规范的数据,在使用的时候,正则表达式中的每一个捕获组对应了Hive表中的一个字段
案例:
文件内容如下:

192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /asf.avi HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /bupper.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /bupper.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /bg-button HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /bbutton.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /asf.jpg HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tomcat.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tbutton.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tinput.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tbg.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /tomcat.css HTTP/1.1" 304 -

需要提取其中的字段进行使用:

create table log (host string,time string,request string,paths string,way string,stat int) row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe' with serdeproperties ("input.regex" = "(.*) \-\- \\[(.*)\\] \"(.*) (.*) (.*)\" ([0-9]+) \-") stored as textfile;

2.beeline远程连接

简介:
beeline是hive提供的一种用于远程连接Hive的方式,其提供了表格形式来进行进行展现
如果使用这种方式,需要先后台启动hiveserver2
启动方式:

beeline -u jdbc:hive2://IP地址:10000/库名

注意:此种方式的情况下,默认是不对用户名和密码进行验证

3.View视图

概述:
Hive支持视图,但是不支持物化视图
只能查询,不支持加载数据
视图的创建只是保存一份元数据,只有在查询视图的时候才会执行对应的子查询
视图定义中若包含了order by/limit等语句,且查询视图时也定义了order by/limit等语句,则此时视图中的优先级更高
view支持迭代视图
指令:
#创建视图

create view v_stu as select name from stu;

#删除视图

drop view v_stu;

4.索引

概述:
建立索引的目的是为了提高查询效率
Hive中没有主键的概念,所以默认也是没有索引的
指令:
#创建索引

create index s_index on table stu(id) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in table stu_index;

#重建索引

alter index s_index on stu rebuild;

#删除索引,需要注意的是在删除索引的时候会把对应的表一起删除

drop index s_index on stu;

5.JDBC连接

概述:
Hive实现了JDBC接口,所以可以通过Java代码操作
Hive的JDBC操作在实际应用中用的不多,一般都是在HDFS储存的文件基础上建立外部表来进行查询处理
步骤:
a.服务器端开启HiveServer服务:

sh hive --service hiveserver2 & (以后台线程启动)

b.创建本地工程,导入jar包
hive-jdbc-1.2.0-standalone.jar
hadoop-common-2.7.1.jar
c.创建类

//连接和查询
@Test public void testConnectAndQuery() throws Exception {   // 注册数据库驱动   Class.forName("org.apache.hive.jdbc.HiveDriver");   // 如果用的是hive2服务,则写jdbc:hive2,后面跟上hive服务器的ip以及端口号,端口号默认是10000   Connection conn = DriverManager.getConnection("jdbc:hive2://IP地址:10000/park", "root", "root");   Statement stat = conn.createStatement();   ResultSet rs = stat.executeQuery("select * from stu");   while (rs.next()) {     String name = rs.getString("name");     System.out.println(name);   }   stat.close();   conn.close(); } //创建、插入数据及删除表
@Test public void testInsert() throws Exception {   Class.forName("org.apache.hive.jdbc.HiveDriver");   Connection conn = DriverManager.getConnection("jdbc:hive2://IP地址:10000/park", "root", "root");   Statement stat = conn.createStatement();   // executeUpdate可用于:创建表,向表中插入数据以及删除表   stat.executeUpdate("insert into table stu values(2,'rose')");   stat.executeUpdate("create table stu2(id int,name string) row format delimited fields terminated by ' '");   stat.executeUpdate("drop table stu2");   stat.close();   stat.close(); }

6.元数据

概述:
Hive可以管理hdfs上的文件,用表的形式来管理文件数据。而表名、表里有哪些字段,字段类型、哪张表存在哪个数据下等这些表信息,称之为hive的元数据信息
默认情况下,Hive的元数据信息不是存在HDFS上的,而是存在Hive自带的Derby关系型数据库里的
Hive安装完成之后,通常都需要替换元数据库,目前Hive只支持Derby和MySQL两种元数据库,需要将元数据库替换为MySQL
元数据的默认字符集是ISO8859-1
Derby存在的问题
Derby数据库是一种文件型的数据库,在进入时会检查当前目录下是否有metastore_db文件夹用来存储数据库数据,如果有就直接使用,如果没有就创建,这样一旦换一个目录,元数据就找不到了
Derby数据库是一个单用户的数据库,无法支持多用户同时操作,而hive如果使用derby作为元数据库,则也只能支持单用户操作,这就导致在数据量大连接多的情况下会产生大量连接的积压
Mysql配置:
a.将Mysql驱动包上传到Hive安装目录的lib目录下
b.进入conf目录下,编辑新的配置文件,名字为:hive-site.xml

<configuration>
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://IP地址: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>root</value>
  </property>
</configuration>

c.进入Hive ,进入bin目录,执行:sh hive
如果出现:Access denied for user 'root'@'主机名' (using password: YES)这个错误,指的是当前用户操作MySQL数据库的权限不够
d.进入到MySQL数据库,进行权限分配,执行

mysql> grant all privileges on *.* to 'root'@'主机名' identified by 'root' with grant option;
mysql> grant all on *.* to 'root'@'%' identified by 'root';
mysql> flush privileges;

e.进入mysql数据库,执行:

create database hive character set latin1;

f.启动hive客户端
g.以上步骤都做完后,再次进入mysql的hive数据,发现有如下的表:

h.可以通过SQLyog来连接数据库

九.Hive中的数据类型

1.基本类型

tinyint(对应Java中的byte)
smallint(对应Java中的short)
int(对应Java中的int)
bigint(对应Java中的long)
boolean(对应Java中的boolean)
float(对应Java中的float)
double(对应Java中的double)
string(对应Java中的String)
timestamp(对应Java中的TimeStamp)
binary(对应Java中的byte[])

2.复杂类型

a.数组类型 array
例子1:
原始数据:

100,200,300 
200,300,500

建表语句:

create external table ex(vals array<int>) row format delimited fields terminated by '\t' collection items terminated by ',' location '/ex';

查询每行数组的个数,查询语句:

select size(vals) from ex;

注:hive 内置函数不具备查询某个具体行的数组元素,需要自定义函数来实现
例子2:
原始数据:

100,200,300 tom,jary
200,300,500 rose,jack

建表语句:

create external table ex1(info1 array<int>,info2 array<string>) row format delimited fields terminated by '\t' collection items terminated by ',' location '/ex';

b.map类型
例子1:
原始数据:

tom,23
rose,25
jary,28

建表语句:

create external table m1 (vals map<string,int>) row format delimited fields terminated by '\t' map keys terminated by ',' location '/map';

查询语句:

select vals['tom'] from m1;

例子2:
原始数据:

tom 192.168.234.21
rose 192.168.234.21
tom 192.168.234.22
jary 192.168.234.21

建表语句 :

create external table ex (vals map<string,string>) row format delimited fields terminated by '\t' map keys terminated by ' ' location '/ex';

注意:map类型,列的分割符必须是\t
查询语句

select vals['tom'] from ex where vals['tom'] is not null;

如果想做去重工作,可以调用distinct内置函数

select distinct(ip) from (select vals['tom'] ip from ex where vals['tom'] is not null)ex1;或者select distinct(vals['tom']) from m2 where vals['tom'] is not null;

c.struct 类型
例子:
原始数据:

tom 23
rose 22
jary 26

建表语句:

create external table ex (vals struct<name:string,age:int>)row format delimited collection items terminated by ' ' location '/ex';

查询语句:

select vals.age from ex where vals.name='tom';

3.运算符

=
<>
<
>
<=
>=
IS NULL
IS NOT NULL
LIKE
RLIKE
REGEXP
+
-
*
/
%
&
|
^
~
AND
&&
OR
|
NOT
!

4.函数(略)
概述:
Hive实现了标准的sql,但在这之外,为了提升hive处理数据的能力,还额外提供了很多内置的函数,这些内置函数非常丰富,且可以直接使用,虽然不属于sql原生的语法,但大大的增强了hive处理数据的能力,是hive功能的重要组成部分
Hive除了有内置函数,还允许用户自定义函数
a.数学函数
b.类型转换函数
c.日期函数
d.条件函数
e.字符串函数
f.聚合函数
g.explode
h.自定义函数-UDF

十.Sqoop工具介绍

1.概述:
Sqoop是Apache 提供的工具,用于hdfs和关系型数据库之间数据的导入和导入
可以从hdfs导出数据到关系型数据库,也可以从关系型数据库导入数据到hdfs
2.步骤:
a.准备Sqoop安装包,官网地址:http://sqoop.apache.org
b.配置JDK环境变量和Hadoop的环境变量
c.解压Sqoop的安装包
d.需要将要连接的数据库的驱动包加入Sqoop的lib目录下(本例中用的是MySQL数据库)
e.利用指令操作Sqoop
3.基础指令:
#查看MySQL所有数据库

sh sqoop list-databases --connect jdbc:mysql://IP地址:3306/ -username root -password root

#查看指定数据库下的所有表

sh sqoop list-tables --connect jdbc:mysql://IP地址:3306/hive -username root -password root

#关系型数据库 ->hdfs

create table tabx (id int,name varchar(20));
insert into tabx (id,name) values (1,'aaa'),(2,'bbb'),(3,'ccc'),(1,'ddd'),(2,'eee'),(3,'fff');

#进入到sqoop的bin目录下

sh sqoop import --connect jdbc:mysql://IP地址:3306/test --username root --password root --table tabx --target-dir '/sqoop/tabx' --fields-terminated-by '|' -m 1;

#hdfs ->关系型数据库(Sqoop只能导出数据,不能自动建表。所以在导出之前,要现在MySQL数据库里建好对应的表)

sh sqoop export --connect jdbc:mysql://192.168.150.138:3306/test --username root --password root --export-dir '/sqoop/tabx/part-m-00000' --table taby -m 1 --fields-terminated-by '|';

#查看import的帮助指令

sh sqoop import -help

猜你喜欢

转载自www.cnblogs.com/fanqinglu/p/11838634.html
今日推荐