动态分区
如果往hive里面创建的分区有很多,假设按照某个字段进行分区存储,需要写很多sql语句。hive提供了一种动态分区的功能,可以基于查询参数的位置去推断分区的名称,从而建立分区。
首先看下数据集:
1,小明1,male,24,lol-book-movie,beijing:xisanqi-shanghai:pudong
2,小明2,male,25,lol-book-movie,beijing:xisanqi-shanghai:pudong
3,小明3,female,23,lol-book-movie,beijing:xisanqi-shanghai:pudong
4,小明4,male,23,lol-book-movie,beijing:xisanqi-shanghai:pudong
5,小明5,female,24,lol-movie,beijing:xisanqi-shanghai:pudong
6,小明6,male,25,lol-book-movie,beijing:xisanqi-shanghai:pudong
7,小明7,female,23,lol-book,beijing:xisanqi-shanghai:pudong
8,小明8,female,24,lol-book,beijing:xisanqi-shanghai:pudong
9,小明9,male,23,lol-book-movie,beijing:xisanqi-shanghai:pudong
首先创建一张表来保存这些数据,还未进行分区
hive> create table one (id int,name string,hobby array<string>,address
map<string,string) row format delimited fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
lines terminated by '\n';
开启动态分区,默认是false
hive> set hive.exec.dynamic.partition=true;#默认是false
set hive.exec.dynamic.partition.mode=nonstrict;#开启允许所有分区都是动态的,否则必要要有一个静态分区才能使用,且静态分区要在动态分区的前面
注意: cli模式下的set参数只能是本次会话有效,退出后就无效。如果想永久有效,需要去hive-site.xml下设置。但cli模式下的设置优先级大于hive-site.xml设置。
建立分区表
create table two (id int,name string,hobby array<string>,address map<string,string>)
partitioned by (sex string,age int);
根据表one中的sex和age字段进行分区,注意分区的字段sex,age只能放在hive数据字段的后面。
注意:使用,insert…select 往表中导入数据时,查询的字段个数必须和目标的字段个数相同,不能多,也不能少,否则会报错。但是如果字段的类型不一致的话,则会使用null值填充,不会报错。而使用load data形式往hive表中装载数据时,则不会检查。如果字段多了则会丢弃,少了则会null值填充。同样如果字段类型不一致,也是使用null值填充。
from one
insert into table two partition (sex,age)
select id,name,hobby,address,sex,age destribute by sex,age;#destribute by是控制在map端如果把数据拆分给reduce端,这里加不加都可。hive会根据reduce的个数进行数据分发,默认采用hash算法。
age和sex的顺序也不行错。
查看查询结果
hive> select * from two;
OK
7 小明7 ["lol","book"] {"beijing":"xisanqi","shanghai":"pudong"} female 23
3 小明3 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} female 23
8 小明8 ["lol","book"] {"beijing":"xisanqi","shanghai":"pudong"} female 24
5 小明5 ["lol","movie"] {"beijing":"xisanqi","shanghai":"pudong"} female 24
9 小明9 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} male 23
4 小明4 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} male 23
1 小明1 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} male 24
6 小明6 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} male 25
2 小明2 ["lol","book","movie"] {"beijing":"xisanqi","shanghai":"pudong"} male 25
hive> show partitions two;
OK
sex=female/age=23
sex=female/age=24
sex=male/age=23
sex=male/age=24
sex=male/age=25
Time taken: 0.251 seconds, Fetched: 5 row(s)
静态分区
在插入数据时指定分区
create table three (id int,name string,hobby array<string>,address
map<string,string>)
partitioned by (sex string,age int);
from one
insert into table three partition(age=22,sex='female')
select id,name,hobby,addr;
半自动分区
一部分是静态分区一部分是动态分区
create table five (id int,name string,habby array<string>,addr
map<string,string> partititoned by (sex string,age int);
只需要动态分区age
from one
insert into table five partition (sex='male',age)
select id,name,hobby,address,age;
order by和sort by
order by
Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排
序,所以说,只有hive的sql中制定了order by所有的数据都会到同一个reducer进行处理(不管
有多少map,也不管文件有多少的block只会启动一个reducer)。但是对于大量数据这将会消耗很
长的时间去执行。
这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是
nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一reducer端
进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条
数。
sort by
Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个
reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好
处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就
可以做到全局排序了)