Hive 分割槽 分桶使用
為了對錶進行合理的管理以及提高查詢效率,Hive可以將表組織成“分割槽”。
分割槽是表的部分列的集合,可以為頻繁使用的資料建立分割槽,這樣查詢分割槽中的資料時就不需要掃描全表,這對於提高查詢效率很有幫助。
分割槽是一種根據“分割槽列”(partition column)的值對錶進行粗略劃分的機制。Hive中的每個分割槽對應資料庫中相應分割槽列的一個索引,每個分割槽對應著表下的一個目錄,在HDFS上的表現形式與表在HDFS上的表現形式相同,都是以子目錄的形式存在。
一個表可以在多個維度上進行分割槽,並且分割槽可以巢狀使用。建分割槽需要在建立表時通過PARTITIONED BY子句指定,例如:
CREATE TABLE logs(
timestamp BIGINT,
line STRING
)
PARTITIONED BY (date STRING,country STRING);
在將資料載入到表內之前,需要資料載入人員明確知道所載入的資料屬於哪一個分割槽。
使用分割槽在某些應用場景下能給有效地提高效能,當只需要遍歷某一個小範圍內的資料或者一定條件下的資料時,它可以有效減少掃描資料的數量,前提是需要將資料匯入到分割槽內。
注意:PARTITONED BY子句中定義的列是表中正式的列(分割槽列),但是資料檔案內並不包含這些列。
在Hive裡,為什麼要分割槽?
龐大的資料集可能需要耗費大量的時間去處理。在許多場景下,可以通過分割槽或切片的方法減少每一次掃描總資料量,這種做法可以顯著地改善效能。
資料會依照單個或多個列進行分割槽,通常按照時間、地域或者是商業維度進行分割槽。比如vido表,分割槽的依據可以是電影的種類和評級,另外,按照拍攝時間劃分可能會得到更一致的結果。為了達到效能表現的一致性,對不同列的劃分應該讓資料儘可能均勻分佈。最好的情況下,分割槽的劃分條件總是能夠對應where語句的部分查詢條件。
Hive的分割槽使用HDFS的子目錄功能實現。每一個子目錄包含了分割槽對應的列名和每一列的值。但是由於HDFS並不支援大量的子目錄,這也給分割槽的使用帶來了限制。我們有必要對錶中的分割槽數量進行預估,從而避免因為分割槽數量過大帶來一系列問題。
Hive查詢通常使用分割槽的列作為查詢條件。這樣的做法可以指定MapReduce任務在HDFS中指定的子目錄下完成掃描的工作。HDFS的檔案目錄結構可以像索引一樣高效利用。
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
網上有篇關於hive的partition的使用講解的比較好,轉載了:
一、背景
1、在Hive Select查詢中一般會掃描整個表內容,會消耗很多時間做沒必要的工作。有時候只需要掃描表中關心的一部分資料,因此建表時引入了partition概念。
2、分割槽表指的是在建立表時指定的partition的分割槽空間。
3、如果需要建立有分割槽的表,需要在create表的時候呼叫可選引數partitioned by,詳見表建立的語法結構。
二、技術細節
1、一個表可以擁有一個或者多個分割槽,每個分割槽以資料夾的形式單獨存在表文件夾的目錄下。
2、表和列名不區分大小寫。
3、分割槽是以欄位的形式在表結構中存在,通過describe table命令可以檢視到欄位存在,但是該欄位不存放實際的資料內容,僅僅是分割槽的表示。
4、建表的語法(建分割槽可參見PARTITIONED BY引數):
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name data_type [COMMENT col_comment], ...)] [COMMENT table_comment] [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] [ROW FORMAT row_format] [STORED AS file_format] [LOCATION hdfs_path]
5、分割槽建表分為2種,一種是單分割槽,也就是說在表文件夾目錄下只有一級資料夾目錄。另外一種是多分割槽,表文件夾下出現多資料夾巢狀模式。
a、單分割槽建表語句:create table day_table (id int, content string) partitioned by (dt string);單分割槽表,按天分割槽,在表結構中存在id,content,dt三列。
b、雙分割槽建表語句:create table day_hour_table (id int, content string) partitioned by (dt string, hour string);雙分割槽表,按天和小時分割槽,在表結構中新增加了dt和hour兩列。
表文件夾目錄示意圖(多分割槽表):
6、新增分割槽表語法(表已建立,在此基礎上新增分割槽):
ALTER TABLE table_name ADD partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ... partition_spec: : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)
使用者可以用 ALTER TABLE ADD PARTITION 來向一個表中增加分割槽。當分割槽名是字串時加引號。例:
ALTER TABLE day_table ADD PARTITION (dt='2008-08-08', hour='08') location '/path/pv1.txt' PARTITION (dt='2008-08-08', hour='09') location '/path/pv2.txt';
7、刪除分割槽語法:
ALTER TABLE table_name DROP partition_spec, partition_spec,...
使用者可以用 ALTER TABLE DROP PARTITION 來刪除分割槽。分割槽的元資料和資料將被一併刪除。例:
ALTER TABLE day_hour_table DROP PARTITION (dt='2008-08-08', hour='09');
8、資料載入進分割槽表中語法:
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
例:
LOAD DATA INPATH '/user/pv.txt' INTO TABLE day_hour_table PARTITION(dt='2008-08- 08', hour='08'); LOAD DATA local INPATH '/user/hua/*' INTO TABLE day_hour partition(dt='2010-07- 07');
當資料被載入至表中時,不會對資料進行任何轉換。Load操作只是將資料複製至Hive表對應的位置。資料載入時在表下自動建立一個目錄,檔案存放在該分割槽下。
9、基於分割槽的查詢的語句:
SELECT day_table.* FROM day_table WHERE day_table.dt>= '2008-08-08';
10、檢視分割槽語句:
hive> show partitions day_hour_table; OK dt=2008-08-08/hour=08 dt=2008-08-08/hour=09 dt=2008-08-09/hour=09
三、總結
1、在 Hive 中,表中的一個 Partition 對應於表下的一個目錄,所有的 Partition 的資料都儲存在最字集的目錄中。
2、總的說來partition就是輔助查詢,縮小查詢範圍,加快資料的檢索速度和對資料按照一定的規格和條件進行管理。
——————————————————————————————————————
hive中關於partition的操作:
hive> create table mp (a string) partitioned by (b string, c string);
OK
Time taken: 0.044 seconds
hive> alter table mp add partition (b='1', c='1');
OK
Time taken: 0.079 seconds
hive> alter table mp add partition (b='1', c='2');
OK
Time taken: 0.052 seconds
hive> alter table mp add partition (b='2', c='2');
OK
Time taken: 0.056 seconds
hive> show partitions mp ;
OK
b=1/c=1
b=1/c=2
b=2/c=2
Time taken: 0.046 seconds
hive> explain extended alter table mp drop partition (b='1');
OK
ABSTRACT SYNTAX TREE:
(TOK_ALTERTABLE_DROPPARTS mp (TOK_PARTSPEC (TOK_PARTVAL b '1')))
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Drop Table Operator:
Drop Table
table: mp
Time taken: 0.048 seconds
hive> alter table mp drop partition (b='1');
FAILED: Error in metadata: table is partitioned but partition spec is not specified or tab: {b=1}
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask
hive> show partitions mp ;
OK
b=1/c=1
b=1/c=2
b=2/c=2
Time taken: 0.044 seconds
hive> alter table mp add partition ( b='1', c = '3') partition ( b='1' , c='4');
OK
Time taken: 0.168 seconds
hive> show partitions mp ;
OK
b=1/c=1
b=1/c=2
b=1/c=3
b=1/c=4
b=2/c=2
b=2/c=3
Time taken: 0.066 seconds
hive>insert overwrite table mp partition (b='1', c='1') select cnt from tmp_et3 ;
hive>alter table mp add columns (newcol string);
location指定目錄結構
hive> alter table alter2 add partition (insertdate='2008-01-01') location '2008/01/01';
hive> alter table alter2 add partition (insertdate='2008-01-02') location '2008/01/02';