[老实李]HIVE学习笔记

一、HIVE简介

Hive是一种建立在Hadoop文件系统上的数据仓库架构,并对存储在HDFS中的数据进行分析和管理;它可以将结构化的数据文件映射为一张数据库表,并提供完整的 SQL 查询功能,可以将 SQL 语句转换为 MapReduce 任务进行运行,通过自己的 SQL 去 查询分析需要的内容,这套 SQL 简称 Hive SQL(HQL),使不熟悉 MapReduce 的用户也能很方便地利用 SQL 语言对数据进行查询、汇总、分析。同时,这个语言也允许熟悉 MapReduce 开发者们开发自定义的mappers和reducers来处理内建的mappers和reducers无法完成的复杂的分析工作。Hive还允许用户编写自己定义的函数UDF,用来在查询中使用。Hive中有3种UDF:User Defined Functions(UDF)、User Defined Aggregation Functions(UDAF)、User Defined Table Generating Functions(UDTF)。也就是说对存储在HDFS中的数据进行分析和管理,我们不想使用手工,我们建立一个工具吧,那么这个工具就可以是hive。

二、简单的命令

//展示方法名列表
show functions;
//简单方法的解释
desc function split;

image.png

//解释方法名并且举个例子
desc function extended split;

[老实李]HIVE学习笔记_第1张图片
image.png

//查找sp开头的方法名
show functions like 'sp.*';

image.png

三、分区和分桶

1.分区

(1)什么是分区?
分区其实就是再HDFS上存储的时候分了一个相应的分区文件夹,比如你的一个表 partition_test,然后根据日期分区的话,最后HDFS上的就是类似这样的结构
/user/hive/warehouse/partition_test/stat_date=2015-01-18/province=beijing----显示刚刚创建的分区

(2)内部表和外部表有什么区别?
1.内部表删除的时候会将表的数据和元数据信息全部删除,而外部表仅仅删除外部表的元数据,数据是不会删除的。

  1. 内部表在load data的时候会将数据转移。也就是说 load data inpath '/input/edata' into table et; 这句话会把HDFS上的/input/edata文件移动到表et的location下面。而外部表不会。
    3.内部表和外部表都会在 /user/hive/warehouse/新建一个表的目录(如果不指定location的话)

(3)内部分区表和外部分区表
创建一个简单的内部分区表

create table partition_internal(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

//为内部分区表指定分区
ALTER TABLE partition_internal ADD PARTITION (province='henan',city='zhengzhou');
//加载数据到内部分区表 这个时候会移动数据
LOAD DATA INPATH '/user/hive/external01' INTO TABLE partition_internal PARTITION(province='henan',city='zhengzhou');
创建外部分区表

create  external table partition_external(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';
create  external table partition_external(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t'

LOCATION '/user/hive/external02';

为外部分区表添加分区
ALTER TABLE partition_external ADD PARTITION (province='shanxi',city='xian') LOCATION '/user/hive/external02';

//查看分区
show partitions partition_external;

//删除分区
ALTER TABLE student_partition_external DROP PARTITION(province='guangzhou',city='shenzhen');

//向多个分区插入数据,命令如下。
from partition_test_input

insert overwrite table partition_test partition(stat_date='2015-01-18',province='jiangsu') select member_id,name from partition_test_input where stat_date='2015-01-18' and province='jiangsu'

insert overwrite table partition_test partition(stat_date='2015-01-28',province='sichuan') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='sichuan'

insert overwrite table partition_test partition(stat_date='2015-01-28',province='beijing') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='beijing';

(4)动态分区
按照上面的方法向分区表中插入数据,如果数据源很大,针对一个分区就要写一个 insert ,非常麻烦。使用动态分区可以很好地解决上述问题。动态分区可以根据查询得到的数据自动匹配到相应的分区中去。

1、启动动态分区功能(默认没有启动)
set hive.exec.dynamic.partition = true;

2、设置所有分区都是动态的
set hive.exec.dynamic.partition.mode=nostrict;

3、准备两个表:一个普通外部表student_external01,一个分区外部表student02
而且要保证分区表结构student02和student_external01一致
我们以student_external01表为例,但是少两个分区字段,所以我们再增加两个字段。
ALTER TABLE student_external01 ADD COLUMNS(province STRING,city STRING);

4、先往外部表student_external01中加载数据(实际上现在外部表student_external01中已经有数据了,因为创建该表时指定了location)
LOAD DATA INPATH '/user/hive/external02/student.txt' INTO TABLE student_external01;

5、利用动态分区向表中插入数据
//先创建分区外部表student02

create  external table student02(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

PARTITIONED BY(province STRING,city STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

//利用动态分区向表中插入数据
INSERT OVERWRITE TABLE student02 PARTITION(province,city) SELECT * FROM student_external01 ;
然后数据就会动态分区,把对应的数据放到对应的分区下。

[老实李]HIVE学习笔记_第2张图片
image.png

2.桶操作

Hive 中 table 可以拆分成 Partition table 和 桶(BUCKET),分区提供了一个隔离数据和优化查询的便利方式,不过并非所有的数据都可形成合理的分区,尤其是需要确定合适大小的分区划分方式,(不合理的数据分区划分方式可能导致有的分区数据过多,而某些分区没有什么数据的尴尬情况)分桶是将数据集分解为更容易管理的若干部分的另一种技术。

数据分桶的原理: 跟MR中的HashPartitioner的原理一模一样, 按照分桶字段的hash值去模除以分桶的个数

和分区的区别:分桶中的字段是原始数据中存在的,而分区字段在原始文件中并不存在。比如我们上面的那个分区province和city字段就是不在student02中的(如果指定了分区并且表的字段中还包含这两个字段的话,hive会报错的)

1、开启分桶功能

set hive.enforce.bucketing=true;

2、创建桶表

CREATE TABLE IF NOT EXISTS bucket_table(

id INT COMMENT 'student id',

name  STRING COMMENT 'student name',

age INT COMMENT 'student age')

CLUSTERED BY(id) INTO 3 BUCKETS

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\t';

3、插入数据到桶表中
INSERT OVERWRITE TABLE bucket_table SELECT id,name,age FROM student_external01;

二.HIVE复合类型

hive提供了复合数据类型:

1.Structs: structs内部的数据可以通过DOT(.)来存取。例如,表中一列c的类型为STRUCT{a INT; b INT},我们可以通过c.a来访问域a。

  1. 建表
hive> create table student_test(id INT, info struct< name:STRING, age:INT>)

> ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

> COLLECTION ITEMS TERMINATED BY ':';

'FIELDS TERMINATED BY' :字段与字段之间的分隔符。'COLLECTION ITEMS TERMINATED BY' :一个字段各个item的分隔符。

  1. 导入数据(注意最后不要带空格不然识别就是NULL)
$ cat test5.txt

1,zhou:30

2,yan:30

3,chen:20

4,li:80

hive> LOAD DATA LOCAL INPATH '/home/hadoop/djt/test5.txt' INTO TABLE student_test;

  1. 查询数据

hive> select info.age from student_test;

2.Map(K-V对):访问指定域可以通过["指定域名称"]进行。例如,一个Map M包含了一个group-》gid的kv对,gid的值可以通过M['group']来获取。

  1. 建表
hive> create table employee(id string, perf map< string, int>)

 ROW FORMAT DELIMITED

 FIELDS TERMINATED BY '\t'

COLLECTION ITEMS TERMINATED BY ','

MAP KEYS TERMINATED BY ':';

‘MAP KEYS TERMINATED BY’ :key value分隔符
  1. 导入数据
$ cat test7.txt

1 job:80,team:60,person:70

2 job:60,team:80

3 job:90,team:70,person:100

hive> LOAD DATA LOCAL INPATH '/home/work/data/test7.txt' INTO TABLE employee;

  1. 查询

hive> select perf['person'] from employee;

3)Array:array中的数据为相同类型。例如,假如array A中元素['a','b','c'],则A[1]的值为'b'

3.Array使用

  1. 建表
hive> create table class_test(name string, student_id_list array< INT>)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY ','

COLLECTION ITEMS TERMINATED BY ':';
  1. 导入数据
$ cat test6.txt

034,1:2:3:4

035,5:6

036,7:8:9:10

hive> LOAD DATA LOCAL INPATH '/home/work/data/test6.txt' INTO TABLE class_test ;

  1. 查询

hive> select student_id_list[3] from class_test;

三、HIVE的join用法

https://blog.csdn.net/shenxiaoming77/article/details/49489713

四、HIVE的数据删除

1.删除指定行

[老实李]HIVE学习笔记_第3张图片
image.png

insert overwrite table A select id,name from A where id !=2;

2.删除表中所有数据
truncate table table_name;

五、HIVE数据分析结果的保存

https://blog.csdn.net/u010159842/article/details/70193687

六、hive中order by,sort by, distribute by, cluster by作用以及用法

orderby 就一个reduce, sortby是指定几个reduce就是几个reduce进行排序,但是并不能保证所有的数据都是有序的

1. order by

Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有hive的sql中制定了order by所有的数据都会到同一个reducer进行处理(不管有多少map,也不管文件有多少的block只会启动一个reducer)。但是对于大量数据这将会消耗很长的时间去执行。
这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。

2. sort by

Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。

3. distribute by和sort by一起使用

ditribute by是控制map的输出在reducer是如何划分的,举个例子,我们有一张表,mid是指这个store所属的商户,money是这个商户的盈利,name是这个store的名字


[老实李]HIVE学习笔记_第4张图片
image.png

执行hive语句:
select mid, money, name from store distribute by mid sort by mid asc, money asc
我们所有的mid相同的数据会被送到同一个reducer去处理,这就是因为指定了distribute by mid,这样的话就可以统计出每个商户中各个商店盈利的排序了(这个肯定是全局有序的,因为相同的商户会放到同一个reducer去处理)。这里需要注意的是distribute by必须要写在sort by之前。

4. cluster by

cluster by的功能就是distribute by和sort by相结合,如下2个语句是等价的:
select mid, money, name from store cluster by mid
select mid, money, name from store distribute by mid sort by mid
如果需要获得与3中语句一样的效果:
select mid, money, name from store cluster by mid sort by money
注意被cluster by指定的列只能是降序,不能指定asc和desc。

你可能感兴趣的:([老实李]HIVE学习笔记)