不多說,直接上干貨!
Hive還可以把表或分區,組織成桶。將表或分區組織成桶有以下幾個目的:
第一個目的是為看取樣更高效,因為在處理大規模的數據集時,在開發、測試階段將所有的數據全部處理一遍可能不太現實,這時取樣就必不可少。
第二個目的是為了獲得更好的查詢處理效率。
桶為了表提供了額外的結構,Hive在處理某些查詢時利用這個結構,能給有效地提高查詢效率。
桶是通過對指定列進行哈希計算來實現的,通過哈希值將一個列名下的數據切分為一組桶,並使每個桶對應於該列名下的一個存儲文件。
在建立桶之前,需要設置hive.enforce.bucketing屬性為true,使得hive能識別桶。
以下為創建帶有桶的表的語句:
CREATE TABLE bucketed_user( id INT, name String ) CLUSTERED BY (id) INTO 4 BUCKETS;
向桶中插入數據,這里按照用戶id分成了4個桶,在插入數據時對應4個reduce操作,輸出4個文件。
分區中的數據可以被進一步拆分成桶,bucket,不同於分區對列直接進行拆分,桶往往使用列的哈希值進行數據采樣。
在分區數量過於龐大以至於可能導致文件系統崩潰時,建議使用桶。
桶的數量是固定的。
Hive使用基於列的哈希函數對數據打散,並分發到各個不同的桶中從而完成數據的分桶過程。
注意,hive使用對分桶所用的值進行hash,並用hash結果除以桶的個數做取余運算的方式來分桶,保證了每個桶中都有數據,但每個桶中的數據條數不一定相等。
哈希函數的選擇依賴於桶操作所針對的列的數據類型。除了數據采樣,桶操作也可以用來實現高效的Map端連接操作。
記住,分桶比分區,更高的查詢效率。
如何進行桶操作?
例子1
1、創建臨時表 student_tmp,並導入數據。
hive> desc student_tmp; hive> select * from student_tmp;
2、創建 student 表。經過分區操作過后的表已經被拆分成2個桶。
create table student( id int, age int, name string ) partitioned by (stat_date string) clustered by (id) sorted by(age) into 2 bucket row format delimited fields terminated by ',';
分區中的數據可以被進一步拆分成桶!!!正確理解
所有,桶,先partitioned by (stat_date string)
,再,clustered by (id) sorted by(age) into 2 bucket
3、設置環境變量。
hive> set hive.enforce.bucketing=true;
4、插入數據
hive> from student_tmp insert overwrite table student partition(stat_date='2015-01-19') select id,age,name where stat_date='2015-01-18' sort by age;
這都是固定的格式,一環扣一環的。
5、查看文件目錄
$ hadoop fs -ls /usr/hive/warehouse/student/stat_date=2015-01-19/
6、查看 sampling 數據。
tablesample 是抽樣語句,語法如下
tablesample(bucket x out of y)
y 必須是 table 中 BUCKET 總數的倍數或者因子。
例子2
在下面的例子中,經過分區操作過后的表已經被拆分成100個桶。
CREATE EXTERNAL TABLE videos_b( prodicer string, title string, category string ) PARTITIONED BY(year int) CLUSTERED BY(title)INTO 100 BUCKETS;
現在,我們開始填充這張帶桶操作的表:
set hive.enfirce.bucketinig=true; FROM videos INSERT OVERWRITE TABLE videos_b PARTITION(year=1999) SELECT producer,title,string WHERE year=2009;
如果不使用set hive.enforce.bucketing=true這項屬性,我們需要顯式地聲明set mapred.reduce.tasks=100來設置Reducer的數量。
此外,還需要在SELECT語句后面加上CLUSTERBY來實現INSERT查詢。
下面是不使用桶設置的例子:
set mapred.reduce.tasks=100; FROM videos INSERT OVERWRITE TABLE videos_b PARTITION(year=1999) SELECT producer,title,string WHERE year=2009 CLUSTER BY title;
在Hive的文檔中可以找到有關桶的更多細節:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL