Hive的起源
Hive起源于Facebook(美国的一个社交服务网络),因Facebook有着大量的数据需要处理,而Hadoop是一个开源可以轻松处理大量的数据项目。但是Hadoop的MapReduce程序对于Java程序员来说比较容易写,对于其他语言使用者来说不太方便,因此Facebook开始研发Hive,实现了对Hadoop使用类SQL的查询方式(实际后台转化为了MapReduce过程),让那些非Java程序员,只要熟悉sql语法也可以方便地使用Hadoop处理大量的数据,节约了学习成本。
Hive概述
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,它提供了一系列的工具,可以用来进行数据的提取、转化、加载,简称ETL(Extract Transform Load),也可以叫做数据清洗。是一种可以存储、查询和分析存储在Hadoop中的大规模数据机制,Hive定义了简单的类sql查询语言,称为HiveQL。Hive 并非为联机事务处理而设计,Hive 并不提供实时的查询和基于行级的数据更新操作。 Hive 的最佳使用场合是大数据集的离线批处理作业,例如,网络日志分析。
数据仓库的特征
1.数据仓库是多个异构数据源所集成的。
2.数据仓库储存的一般是历史数据,大多数的应用场景是读取数据(数据分析),所以数据仓库是弱事务的。
3.数据库是为捕获数据而设计,数据仓库是为了分析数据而设计。
4.数据仓库是时变的,数据存储从历史的角度提供信息,即数据仓库中的关键结构都隐式或者显示地包含时间元素。
5.数据仓库是弱事务的,因为数据仓库存的是历史数据,一般都是应用在数据读取(分析)场景。
数据仓库与数据库的区别:
数据库属于OLTP(Online Transaction Processing)联机事务处理系统,涵盖了企事业大部份的日常操作,如购物、库存、制造、银行、工资、注册、记账等等,比如Mysql oracle等关系型数据库。
数据仓库属于OLAP(Online Transaction Processing)联机分析处理系统,如Hive Hbase等。
OLTP是面向用户的,用于事务的处理以及客户的查询处理。OLAP是面向市场的,用于数据的分析。
OLAP通常会集成多个异构数据源的数据,数据量巨大。
OLTP系统的访问由于要保证原子性,所以有事务机制和恢复机制。
OLAP系统一般存储的是历史数据,所以大部分都 是只读操作,不需要事务。
OLTP系统与OLAP系统的比较
Hive的HQL
HQL语法十分类似SQL语法,是Hive用来进行分布式的计算语句,在执行的过程中底层会将HQL转换为MapReduce去执行,所以Hive其实是基于Hadoop的一种分布式计算框架,本质上是一种离线大数据分析工具。
Hive基础指令
show databases; 查看有哪些数据库。
create database hive; 创建hive数据库。创建的数据库实际是在Hadoop的HDFS文件系统里创建一个目录节点,统一存在: /user/hive/warehouse 目录下。
use hive; 进入hive数据库。
show tables; 查看当前数据库下所有的表。
create table user(id int,name string); 创建user表以及相关的两个字段。(在Hive里用的是string,不用char和varchar。此外,所创建的表,也是HDFS里的一个目录节点)
insert into user values(1,‘tom’); 向user表里面插入一条数据,(HDFS不支持数据的修改和删除,但是在2.0版本后支持数据追加,实际上INSERT INTO语句执行的是追加操作,注意:hive支持查询,行级别的插入,但是不支持行级别的删除和修改,hive的操作实际是执行一个job任务,调用的是Hadoop的MR)。
select * from user; 查看表数据,也可以根据字段来查询,如:select id from user;
drop table user; 删除user表。
load data local inpath ‘/home/1.txt’ into table user; 加载home目录下1.txt文件里的数据到user表里。
load data inpath ‘info/1.txt’ into table user; 加载HDFS中info目录下1.txt文件的数据到user表。注意与上一个加载 指令的区分。
create table user(id int,name string) row format delimited fields terminated by ’ '; 创建user表,并指定分割符为空格。(此时,把外部表导入hive,就可以查询出数据。)
desc user; 查看user的表结构。
create table user2 like user; 创建一张user2表,表结构和user表结构相同。
insert overwrite table user2 select * from user; 把user表数据插入到user2表中。
alter table user rename to user1; 把表user重命名为user1。
alter table user add columns(age,int); 为表user增加一个列字段age,类型为int。
exit 退出hive。注意:当退出hive后,我们可以尝试做这样的一件事:之前我们是在bin目录执行:sh hive 进入的现在,我们换一个目录来进入hive,比如: sh /bin/hive 来进入当我们查看数据库或查看表时,发现之前建立的hive和user表都没有了。
原因:hive可以管理hdfs上的文件,用表的形式来管理文件数据。而表名、表里有哪些字段,字段类型、哪张表存在哪个数据下等这些表信息,称之为hive的元数据信息。
知识点:hive的元数据信息不是存在hdfs上的,而是存在hive自带的derby关系型数据库里的。
即hive管理的数据是在hdfs上的,hive的元数据信息是存在系型数据库里的。
上述问题出现的原因就是由于derby数据库引起的,这个数据库功能不完善,仅用于测试。derby数据库存储hive元数据的方式:当在bin目录下进入hive时,derby数据会在bin目录下生成一个metastore_db目录,将元数据信息存在这个目录下。当换个目录,比如在home 目录下hive时,derby又会在home目录下生成一个metastore_db目录,存储元数据信息。
解决办法:将默认使用的derby数据库换成mysql数据库。
Hive的内部表和外部表
内部表:先在hive里面建一张表,然后向这个表里面插入数据,也可以通过加载外部文件来插入数据,这样的表叫内部表。可以简单理解为先有表,再有数据的表叫内部表,内部表的特点:当内部表被删除时,对应的HDFS的数据也会被删除。
外部表:HDFS里面已经有数据,例如有一个1.txt文件,里面存储了这样的数据:
1 tom
2 rose
3 bob
然后通过Hive创建一张表来管理这个文件数据,这张表就叫外部表。可以简单理解为先有数据,再建立的hive表就叫外部表。外部表特点:删除外部表,对应的HDFS数据依然存在,在实际生产环境中,我们创建的大多数都是外部表。
创建外部表的命令:create external table user(id int,name string) row format delimited fields terminated by ’ ';
内部表和外部表的区别
最大的区别是就当在hive执行 drop table user; 时,如果user是内部表,则对应HDFS的目录节点也会删除,如果是外部表,HDFS对应的目录节点不会被删除。
Hive分区表
在Hive Select查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作,有时候我们只需要扫描表中的一部分数据,因此建表时引入了partition概念。上面我们说了hive有两种表,内部和外部表,都可以是分区表。
分区表的作用:可以避免查询整表,在生产环境下,基本都是建立带有分区字段的表,在查询时,带上分区条件。
一个表可以拥有一个或者多个分区,分区表在HDFS中,一个分区就对应一个目录。
分区表的实际应用:例如以天为单位来建立分区,这样方便管理表数据,尤其是按日期查询很方便。
创建分区表的语法:create table book(id int,name string) partitioned by (category string) row format delimited fields terminated by ’ ';
注意:在创建分区表时,partitoned字段可以不在字段列表中,生成的表中自动就会具有该字段,category是自定义的字段。还有terminated by ’ ',单引号中是空格那么加载文件的数据也需要是空格隔开,如:cnbook.txt文件中1 book1。
分区表加载数据语法:
load data local inpath ‘/home/cnbook.txt’ overwrite into table book partition (aaa=‘cn’); 加载home目录下cnbook.txt文件的内容到book表并分区为cn。
load data local inpath ‘/home/enbook.txt’ overwrite into table book partition (aaa=‘en’); 加载home目录下enbook.txt文件的内容到book表并分区为en。
我们检查一下HDFS下发现分区也是一个目录:
select * from book; 查询book下的所有数据。
select * from book where aaa=‘cn’; 只查询cn分区的数据。
通过创建目录来增加分区:
如果想先在HDFS的目录下自己创建一个分区目录,然后在此目录下上传文件,此时手动创建目录是无法被hive使用的,因为元数据库中没有记录该分区。如
如果需要将自己创建的分区也能被识别,需要执行:
alter table book add partition (aaa=‘an’) location ‘/user/hive/warehouse/park01.db/book/aaa=an’; 这行命令的作用是在元数据Dock表里创建对应的元数据信息。
删除分区:alter table book drop partition(aaa=‘an’);
修改分区:alter table book partition(aaa=‘an’) rename to partition(aaa=‘bn’);
Hive的分桶表
分桶是相对分区进行更细的划分,分桶将整个数据内容安照某列属性值的hash值进行区分,如:要按照name属性分为3个桶,就是对name属性值的hash值对 3 取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。
如何使用分桶表
1.创建带桶的 table :
create table teacher(name string) clustered by (name) into 3 buckets row format delimited
fields terminated by ’ ';
2.开启分桶机制:
set hive.enforce.bucketing=true;
3.往表中插入数据:
insert overwrite table teacher select * from temp; //需要提前准备好temp,从temp查询数据写入到 teacher
注意:teacher是一个分桶表,对于分桶表,不允许以外部文件方式导入数据,只能从另外一张表导入数据,分桶表只能是内部表。
temp文件数据样例:
java zhang
web wang
java zhao
java qin
web liu
web zheng
ios li
linux chen
ios yang
ios duan
linux ma
linux xu
java wen
web wu
作用及原理:
分桶的原理是根据指定的列计算hash值取模分桶数量后将数据分开存放,方便数据抽样
select * from teacher tablesample(bucket 1 out of 3 on name);
注:分桶语法 tablesample(bucket x out of y)
y必须是table总 bucket 数的倍数或者因子。hive根据y的大小,决定抽样的比例。
例如:table总共分了3份,当y=3时,抽取(3/3=)1个bucket的数据,当y=6时,抽取(3/6=)1/2个
bucket的数据。
x表示从哪个bucket开始抽取。
例如:table总bucket数为3,tablesample(bucket 3 out of 3),表示总共抽取(3/3=)1个bucket的
数据,抽取第3个bucket的数据。
再例如:table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个
bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。
查询第一个桶里数据,并返回一半的数据:
select * from bucketed_user tablesample(bucket 1 out of 6 on id);
Hive的数据类型
基本数据类型:int、 boolean、 float、 double、string。
复杂数据类型:
数组类型 array
案例1:有元数据
100,200,300
200,300,500
建表语句:create exterbal table ex(vals array) row 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,info2 array) row format delimited fields terminated by ‘\t’ collection items terminated by ‘,’ location ‘/ex’;
查询结果:
map类型
案例1
元数据:
tom,23
rose,25
jary,28
建表语句:create external table m1 (vals map
查询tom年龄的语句:select vals[‘tom’] from m1;
案列2,要求查询tom这个人都浏览了哪些网站,并且为null的值不显示
源数据(分隔符为空格):
tom 192.168.234.21
rose 192.168.234.21
tom 192.168.234.22
jary 192.168.234.21
tom 192.168.234.24
tom 192.168.234.21
rose 192.168.234.21
tom 192.168.234.22
jary 192.168.234.21
tom 192.168.234.22
tom 192.168.234.23
建表语句:
create external table ex (vals map
注意: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;
struct 类型
案例
元数据:
tom 23
rose 22
jary 26
建表语句:
create external table ex (vals structname:string,age:int)row format delimited collection items terminated by ’ ’ location ‘/ex’;
查询语句:
select vals.age from ex where vals.name=‘tom’;
Hive常用字符串操作函数
因Hive内容挺多,暂且说这些,后续抽空再说一说Hive特点、Hive的Join操作、Hive解决数据倾斜问题、Hive优化、Hive的分桶表、Hive体系结构、Hive工作流程等。感谢!