Hive動態分區
1、首先創建一個分區表
create table t10(name string)
partitioned by(dt string,value string)
row format delimited fields terminated
by '\t' lines terminated by '\n'
stored as textfile;
2、然后對hive進行設置,使之支持動態分區,
set hive.exec.dynamic.partition.mode=nonstrict;
如果限制是strict,則必須有一個靜態分區,且放在最前面
set hive.exec.dynamic.partition.mode=strict;
3、最后向t10表中插入數據,同時指定分區
insert overwrite table t10 partition(dt='2014010090',value)
select '34' as name,addr as value from t9;
HQL函數
1、order by
按照某些字段進行排序,例如:select clol,clo2... from table_name where condition order by clo1,clo2[asc|desc];order by 后面可以對多列進行排序,默認按照字典進行排序,order by為全局排序,它需要reduce操作,並且只有一個reduce,和配置沒有關系
假如表t2中的數據格式為:
id name
1 zhangsan
2 lisi
3 wangwu
4 sunfei
5 cuiying
對此進行語句:select * from t2 order by id desc,name asc;
對第一列進行降序排列,對第二列進行升序排列。由於order by是全局排序,並且只使用了一個reduce,所以在實際應用中應該盡量少使用order by進行排序
2、group by
按照某些字段的值進行分組,將相同的值放在一起
select col1[,col2],count(),sel_expr(聚合操作)
from table
where condition
group by col1[,col2]
[having]
注意,select后面非聚合列必須出現在group by中,除了普通列就是一些聚合操作,group by后面也可以跟表達式,比如substr(col)
同時,group by 使用了reduce操作,受限於reduce的數量,設置reduce的數量可以mapred.reduce.tasks,輸出文件個數和reduce的個數
相同,文件大小與reduce處理的數據量有關,在實際應用過程中,它存在一些問題,如網絡負載過重以及數據傾斜(在處理數據過程中,從map到reduce的過程是按照key值進行划分,
由key值決定文件是由哪個reduce來執行,假如某一個reduce中處理的key過多,即就是某一個reduce處理任務過多,執行時間過長,導致整個Job作業執行時間過長,在其他reduce任務已經完成后,
這個處理過多reduce的任務會嚴重拖慢整體任務的完成時間,這就是數據傾斜,可以通過將
hive.groupby.skewindata參數設置為true,hive自動啟動優化程序來避免數據傾斜)等問題。
例如:set mapred.reduce.tasks=5;
set hive.groupby.skewindata=true;//數據傾斜時候可以使用
select country,count(1) as num from info group by country;
3、join
兩個表m,n之間按照On條件進行連接,m中的一條記錄和n中的一條記錄組成一條新紀錄,它是等值連接,只有某個值在m和n中同時存在的時候才可以進行連接操作,left outer join 左邊外接,左邊
表中的值無論是否在b中存在的時候,都輸出,右邊表中的值只有在左邊表中存在的時候才輸出,left outer join則相反,left semi join的作用類似於exits, mapjoin則是在map端完成join操作,
不需要reduce,基於內存做join,屬於優化操作
例如:
a表: b表:
co1 co2 co3 co4
1 w 1 f
3 e 1 g
5 r 4 j
對a和b表執行語句:
select s.co1,s.co2,t.co4
from
(select col from a where ...(map端執行))s(左表)
join
(select col from b)t(右表)
on s.co1 = t.co3
where condition(reduce端執行)
其結果為:
1 w f
1 w g
5 e j
執行過程是:對於a表中的每一行數據,在b表中進行遍歷,如果查找到相同的則提取這一樣存在一個新表中。
如果將join修改為:left outer join 則執行結果為:
1 w f
1 w g
5 e j
3 r null
執行原則是:key值必須在a表中存在,但可以不在b表中存在
如果將join修改為:right outer join 則執行結果為:
1 w f
1 w g
5 e j
2 null p
執行原則是:key值必須在b表中存在,但可以不在a表中存在
如果將join修改為:left semi join 則執行結果為:
1 w f
5 e j
執行原則是:首先查看a表中的第一條記錄,如果在b中存在相同記錄則輸出a中的記錄
4、Mapjoin
Mapjoin在map端把小表加載到內存中,然后讀取大表,和內存中的小表完成連接操作,
其中使用了分布緩存技術,它的執行不消耗集群的reduce資源(因為集群的reduce
資源相對短缺),減少了reduce操作,加快程序執行,降低網絡負載,但是,它占用
部分內存,所以加載到內存中的表不能過大,因為每個計算節點都會加載一次,同時
會生成較多的小文件。
通過如下配置,hive自動根據sql選擇使用common join或者map join
set hive.auto.convert.join=true;
hive.mapjoin.smalltable.filesize默認值為25Mb
還可以手動指定:
select/*+mapjoin(n(表名))*/m.col,m.col2,n.col3 from m
join n
on m.col = n.col
總之,mapjoin的使用場景主要有:
關聯操作中有一張表非常小,大表和小表進行關聯
不等值的鏈接操作
5、Hive分桶
(1)對於每一個表或者分區,Hive可以進一步組織成桶,也就是說桶是更為細粒度的數據
范圍划分
(2)Hive是針對某一列進行分桶
(3)Hive采用對列值哈希,然后除以桶的個數求余的方式決定該條記錄存放在哪個桶中
分桶的好處是可以獲得更高的查詢處理效率,使取樣更高效
create table t(id int,name string)
clustered by(id)sorted by(name)into 4 buckets
row format delimited fields terminated by '\t'
stored as textfile;
set hive.enforce.bucketing=true;
6、分桶的使用
select * from t tablesample(bucket 1 out of 2 on id)
這句話的意思是將所有的桶分成兩份,然后取其中的一份
bucket join
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge =true;
set hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
連接兩個在(包含連接列)相同列張划分了桶的表,可以使用Map端連接(Map-site join)
高效的實現,比如Join操作。對於Join操作兩個表有一個相同的列,如果對這兩個表都進
桶操作,那么將保存相同列值得桶進行Join操作就可以,可以大大減少Join的數據量
對於Mapd端連接的情況,兩個表以相同方式划分桶。處理左邊表某個桶的mapper知道右邊表
內相匹配的行在對應的桶內。因此,mapper只需要獲取那個桶(這只是右邊表內存儲數據的
一小部分)即可進行連接。這一優化方法並不一定要求兩個表的桶的個數相同,兩個表的桶
個數是倍數關系也可以。