1. 什么是hive?
hive是基於Hadoop的一個數據倉庫工具,可以將結構化和半結構化的數據文件映射為一張數據庫表,
並提供簡單的sql查詢功能。
注意:
(1)Hive本質是將HDFS轉換成MapReduce的任務進行運算,底層由HDFS來提供數據存儲。
(2)Hive的元數據存儲在SQL上,HBase的元數據存儲在HDFS上。
hive,mapreduce,HDFS關系?
2. Hive的意義(最初研發的原因)?
避免了去寫MapReduce,提供快速開發的能力,減少開發人員的學習成本。
優點:可以寫sql,可擴展性強,容錯性強。
缺點:效率低
3. Hive的內部組成模塊,作用分別是什么?
元數據:Metastore
元數據包括:表名、表所屬的數據庫(默認是default)、表的擁有者、列/分區字段、表的類型(是否是外部表)、表的數據所在目錄等。
推薦使用MYSQL存儲Metastore
4. Hive支持的數據格式?
Text,SequenceFile,ParquetFile,ORC格式RCFILE等。
5. 進入Hiveshell窗口的方式
方式一:
1. 服務端啟動metastore服務:
nohup hive --service metastore > /dev/null 2>&1 &
2. 監控端口
netstat -ntulp | grep 9083
3. 進入hive的客戶端
hive
4. 退出
quit;
5. 全部的客戶端均可訪問hive
方式二:
1. 先啟動metastore
nohup hive --service metastore > /dev/null 2>&1 &
2. 服務端啟動hiveserver2
nohup hiveserver2 > /dev/null 2>&1 &
需要稍等下,啟動服務需要時間
3. 進入命令
(1)先執行beeline,再執行:connect jdbc:hive2://node001:10000
(2)或者直接執行:beeline -u jdbc:hive2://node001:10000 -n root
4. 退出命令行
exit
方式三:
使用-e參數來直接執行hql的語句
[root@node001 ~]# hive -e "show databases;"
[root@node001 ~]# beeline -u jdbc:hive2://node001:10000 -n root -e "use bdp; show tables;"
beeline比hive方式快
[root@node001 ~]# hive -f hello_hive.sql
[root@node001 ~]# beeline -u jdbc:hive2://node001:10000 -n root -f hello_hive.sql
擴展:mestore和hiveserver2兩個服務器的差異
(1)所有的hive集群,如果使用hive的方式登錄客戶端時,每一台虛擬機只要輸入hive命令,都會啟動一個mestore服務,還要指向node001的mestore服務。
而用beeline方式登錄hive客戶端時,它是指向的node001 hiveserver2這個服務,去node001服務器操作。
hiveserver2是有集群的,一台節點可以load data其中一台hiveserver2,但是這個hiveserver2必須是在主節點才可以成功。
6. 簡述Hive主要架構及解析成MR的過程?
Hive元數據默認存儲在derby數據庫,不支持多客戶端訪問,所以需要將元數據存儲在MYSQL中,才支持多客戶端訪問。
元數據包括表名,表所屬的數據庫(默認是default),表的擁有者,列/分區字段,表的類型(是否是外部表),表的數據所在目錄
一般需要借助於其他的數據載體(數據庫),主要用於存放數據庫的建表語句,推薦使用Mysql數據庫存放數據,連接數據庫需要提供:uri,username,password,driver
Hive解析成MR的過程:
Hive通過給用戶提供一系列交互接口,接收到用戶的指令(sql語句),結合元數據(metastore),經過Driver內的解析器,編譯器,優化器,
執行器轉換成mapreduce,提交給hadoop執行,最后將執行返回的結果輸出到用戶交互接口。
7. Hive與傳統數據庫的區別?
Hive和數據庫除了擁有類型的查詢語言之外,無其他相似
查詢語言 | HQL | SQL |
---|---|---|
存儲位置 | HDFS | Raw Device或者Local FS(塊設備或本地文件系統) |
數據格式 | 用戶定義 | 系統決定 |
執行引擎 | MapReduce | 用自己的執行引擎 |
執行速度 | Hive執行延遲度高,但當它數據規模遠遠超過數據庫處理能力時,Hive的並行計算能力就體現優勢了。 | 數據庫執行延遲較低 |
數據更新 | 不支持 | 支持 |
數據規模 | Hive大規模的數據計算,是HDFS的數據規模 | 數據庫能支持得數據規模較小 |
擴展性 | Hive建立在Hadoop上,隨Hadoop的擴展性。 | 數據庫由於ACID語義的嚴格限制,擴展有限。 |
索引0.8版本之后加入位圖索引 | 復雜的索引 | |
執行 | MapReduce | Executor |
執行延遲 | 高 | 低 |
可擴展性 | 高 | 低 |
數據格式:txt,zip,lzo,tar,gz,orc,rcfile,csv....
8. Hive內部表和外部表的區別?
類別 | 外部表 | 內部表 |
---|---|---|
存儲 | 外部表數據由HDFS管理 | 內部表數據由hive自身管理 |
存儲 | 外部表數據存儲位置由自己指定(沒有指定location則在默認地址下新建) | 內部表數據存儲在hive.metastore.warehouse.dir(默認在/user/hive/warehouse) |
創建 | 被external修飾的就是外部表 | 沒被修飾的是內部表 |
刪除 | 刪除外部表僅僅刪除元數據 | 刪除內部表會刪除元數據和存儲數據 |
說明:外部表location
[root@node001 data]# pwd
/data
[root@node001 data]# vim dept.txt
{
10,ACCOUNTING,NEW YORK
20,RESEARCH,DALLAS
30,SALES,CHICAGO
40,OPERATIONS,BOSTON
}
[root@node001 data]# hdfs dfs -put dept.txt /data/;
hive (default)> create external table if not exists dept(
> DEPTNO int,
> DNAME varchar(255),
> LOC varchar(255)
> )
> row format delimited fields terminated by ','
> location '/data/';
# 創建外部表時,在創建的語句添加location'/data',就能直接能把數據讀取出來,不需要再load data
# 此時數據文件在HDFS中的/data路徑下
如果外部表沒有指定地址,則數據存儲在默認路徑中;內部表的數據存儲在默認路徑中。
默認路徑/hive/warehouse
9. Hive中的order by,sord by,distribute by和cluster by的區別。
(1)order by:對數據進行全局排序,只有一個reduce工作
(2)sort by:每個mapreduce中進行排序,一般和distribute by使用,且distribute by寫在sort by前面。
當mapred.reduce.tasks=1時,效果和order by一樣
(3)distribute by:類似MR的Partition,對key進行分區,結合sort by實現分區排序
(4)cluster by:當distribute by和sort by的字段相同時,可以使用cluster by代替,但cluster by只能是升序,不能指定排序規則
在生產環境中order by使用的少,容易造成內存溢出(OOM)
生產環境中distribute by和sort by用的多
10. row_number(), rank(), dense_rank()區別
select name,subject,score
row_number() over(partition by subject order by score desc) rn,
rank() over(partition by subject order by score desc) r,
dense_rank() over(partition by subject order by score desc) dr
from student_score;
11. Hive實現分區?
分區作用:分區就是輔助查詢,縮小查詢范圍,加快數據的檢索速度和對數據按照一定的規格和條件進行管理。
分區過多的壞處:
1.hive如果有過多的分區,由於底層是存儲再HDFS上,HDFS上只用於存儲大文件而非小文件,因為過多的分區會增加nn的負擔
2.hive如果有過多的分區,由於hive轉換為mapreduce,mapreduce會轉化為task。過多的小文件的話,每個文件一個task,
每個task一個JVM實例,JVM的銷毀和開銷會降低系統效率。
注意事項:
當分區過多且數據很大時,可以使用嚴格模式,避免觸發一個大的mapreduce任務。當分區數量過多且數量過大時,執行寬范圍的數據掃描,
會觸發一個很大的mapreduce任務。在嚴格模式下,當where中沒有分區過濾條件會禁止執行。
1.建表:create table tablename(col1 string) partitioned by(col2 string);
2.添加分區:alter table tablename add partition(col2=’202101’);
3.刪除分區:alter table tablename drop partition(col2=’202101’);
12. Hive導出數據的五種方式?
1. insert方式,查詢結果導出到本地或HDFS
本地:load data local inpath ‘/root/student.txt’ into table student;
HDFS:load data inpath ‘/user/hive/data/student.txt’ into table student;
2. Insert方式,往表里插入
insert into table student values(1,’zhanshan’);
3. as select方式,根據查詢結果創建表並插入數據
create table if not exists stu1 as select id,name from student;
4. Location方式,創建表並指定數據的路徑
create external table stu2 like student location '/user/hive/warehouse/student/student.txt';
5. Import方式,先從hive上使用export導出再導入
import table stu3 from "/user/export/student";
13. Hive導出數據的五種方式
1. Insert方式,查詢結果導出到本地或HDFS
# 重寫本地路徑的文件
Insert overwrite local directory "/root/insert/student" select id,name from student;
# 重寫HDFS路徑的文件
Insert overwrite directory "/user/insert/student" select id,name from student;
2. Hadoop命令導出本地
hive>
dfs -get /user/hive/warehouse/student/ 000000_0 /root/hadoop/student.txt
3. hive Shell命令導出
]$
bin/hive -e ‘select id,name from student;’ > /root/hadoop/student.txt
4. Export導出到HDFS
hive>
export table student to ‘/user/export/student’;
5. Sqoop導出
14. 窗口函數
select name,orderdate,cost,
sum(cost) over() as sp1, --所有行相加
sum(cost) over(partition by name) as sp2, --按名字分組,組內相加
sum(cost) over(partition by name order by orderdate) as sp3, --按名字分組並按時間排序
sum(cost) over(partition by name order by orderdate
rows between unbounded preceding and current row) as sp4,--由起點到當前行的聚合
sum(cost) over(partition by name order by orderdate
rows between 1 preceding and current row) as sp5, --由當前一行到當前行的聚合
sum(cost) over(partition by name order by orderdate
rows between 1 preceding and 1 following) as sp6, --由當前行到前后一行的聚合
sum(cost) over(partition by name order by orderdate
rows between current row and unbouded following) as sp7--由當前行到后面所有行的聚合
from business;
lag(col,n) 往前第n行數據
lead(col,n) 往后第n行數據
select name,orderdate,cost,
lag(orderdate,1) over(distribute by name sort by orderdate) as sp1,--上次購買時間
lead(orderdate,1) over(distribute by name sort by orderdate) as sp2--下次購買時間
from business;
# 查詢前20%時間的訂單信息
# ntile(n)就是分組
# ntile(n) 把有序分區中的行分化到n個數據組中,各組的編號從1開始,ntile會返回每行所屬的組編號(n為int類型)
select * from (
# 因為n=5,所以分成了3組,取sorted=1,也就是取其中的第一條,有3條,20%*14=3
select name,orderdate,cost, ntile(5) over(order by orderdate) sorted
from business
) t
where sorted = 1;
15. 如何定義UDF,UDTF函數?
用UDF函數解析公共字段,用UDTF函數解析事件字段
自定義UDF:繼承UDF,重寫evaluate方法
自定義UDTF:繼承GenericUDTF,重寫3個方法,initialize(自定義輸出的列名和類型),process(將結果返回forward(result)),close
16. hive幾種基本表類型
內部表,外部表,分區表,桶表
17. hive創建表的方式及區別?
(1) 普通創建(創建后會有表結構)
create table if not exists student(id string, name string)
row format delimited fields terminated by '\t';
(2)ike克隆表(只帶過來表結構)
create table if not exists student like stu;
(3)as select查詢創建(數據和表結構都帶過來)
create table if not exists student as select id, name from stu;
18. hive元數據存放的位置及區別?
(1)內嵌模式:將元數據保存在本地內嵌的derby數據庫中,內嵌的derby數據庫每次只能訪問一個數據文件,也就意味着它不支持多會話連接。
(2)本地模式:將元數據保存在本地獨立的數據庫中(一般是mysql),這可以支持多會話連接。
(3)遠程模式:把元數據保存在遠程獨立的mysql數據庫中,避免每個客戶端都去安裝mysql數據庫。
19. Hive的分組方式?
(1)row_number()
(2)rank()
(3)dense_rank()
20. Hive數據傾斜問題及解決方案?
1. 數據傾斜介紹
數據傾斜指單個節點任務所處理的數據量遠大於同類型任務所處理的數據量,導致該節點成為整個作業的瓶頸,這是分布式系統不可能避免的問題。
2. 傾斜原因及解決方法
map輸出數據按key hash分配到reduce中,由於key分布不均勻、或者業務數據本省的特點等原因造成的reduce上的數據量差異過大。
1. 任務讀取大文件,最常見的是讀取壓縮的不可分割的大文件。
解決方法:在數據壓縮的時候可以采用bzip2和zip支持文件分割的壓縮算法或者使用像orc,SequenceFile等列式存儲。
2. key分布不均勻
情形:
實際業務中有大量的null值或一些無意義的數據參與到計算機作業中,這些數據可能來自業務未上報
或因數據規范將某類數據進行歸一化變成空值或空字符串等形式,這些與業務無關的數據導致在進行分組聚合
或在執行表連接時發生數據傾斜。
解決方案:
在計算過程中排除含有這類"異常"數據即可
情形:
在多維聚合計算時存在這樣的場景:
select a, b, c, count() I
from T
group by a, b, c with rollup.
對於上述的SQL,可以拆分成4種類型的鍵進行分組聚合,它們分別是
(a,b)、(a,b、null)、(a,null, null)和(null, null,null)
如果T表的數據量很大,並且Map端的聚合不能很好地起到數據壓縮的情況下,會導致Map端產出的數據急速膨脹,這種情況容易導致作業內存溢出的異常。如果T表含有數據傾斜鍵,會加劇Shuffle過程的數據傾斜。
解決方法:
1.對上述的情況我們會很自然的想到拆解上面的SQL語句,將rollup拆解成如下多個普通類型分組聚合的組合
select a, b, c, count(1)from T group by a, b, c;
select a,b, null, count(1) from T group by a,b;
select a,null, null, count(1) from T group by a;
select null, null, null, count(1) from T;
這是很笨拙的方法,如果分組聚合的列遠不止3個列,那么需要拆解的SQL語句會更多。
2.在Hive中可以通過參數(hive,new job,grouping set,cardinaliy)配置的方式自動控制作業的拆解,該參數默認值是30.
該參數表示針對grouping sets/rollups/cubes這類多維聚合的操作,如果最后拆解的鍵組合(上面例子的組合是4)大於該值,
會啟用新的任務去處理大於該值之外的組合。如果在處理數據時,某個分組聚合的列有較大的傾斜,可以適當調小該值.
3. 無法削減中間結果的數據量引發的數據傾斜
無法理解對於參數的修改配置,因為沒有修改過,以后修改的時候着重看一下。
情形:
在一些操作中無法削減中間結果,例如使用collect_list聚合函數,存在如下SQL
hive(default)> select address,collect_list(name) f1 from t_person group by address;
在student tb txt表中,s_age有數據傾斜,但如果數據量大到一定的數量,會導致處理傾斜的Reduce任務產生內存溢出的異常。
針對這種場景,即使開啟hive.groupby.skewinda配置參數,也不會起到優化的作業,反而會拖累整個作業的運行。
啟用該配置參數會將作業拆解成兩個作業,第一個作業會盡可能將Map的數據平均分配到Reduce階段,並在這個階段實現預聚合,以減少第二個作業處理的數據量;第二個作業在第一個作業處理的數據基礎上進行結果的預聚合。
hive.groupby.skewindata的核心作用在於生成的第一個作業能夠有效減少數量。
但是對於collect list這類要求全量操作所有數據的中間結果的函數來說,明顯起不到作用,反而因為引入新的作業增加了磁盤和網絡IO的負擔,而導致性能變得更為低下。
解決方案:
解決這類問題,最直接的方式就是調整Reduce所執行的內存大小,
使用mapreduce educememory mb這個參數(如果是Map任務內存瓶可以調整mapreducemap memorymb)。
但還存在一個問題,如果Hive的客戶端連接的 Hiveserver2一次性需要返回處理的數據很大,
超過了啟動Hiveserver2設置的Jawa(Xmx),也會導致Hiveserver2服務內存溢出。
4.兩個Hive數據表連接時引發的數據傾斜
問題:兩表進行普通的repartition join時,如果表連接的鍵存在傾斜,那么在Shufe階段必然會引起數據傾斜。
解決方法:
Hive的通常做法還是啟用兩個作業,第一個作業處理沒有傾斜的數據,第二個作業將傾斜的數據存到分布式緩存中,分發到各個M即任務所在節點在Map價段完成join操作,即Mapjoin,這避免了Shuffle,從而避免了數據傾斜。
5. SQL語句造成數據傾斜
1.group by
group by優於distinct group
情形:group by維度過小,某值的數量過多,導致處理某值的reduce非常耗時。
解決方式:
采用sum() group by的方式來替換count(distinct) 完成計算
2.count(distinct)
情形:
1.某特殊值過多
2.處理此特殊值的reduct耗時
解決方式:
1.count distinct時,將值為空的情況單獨處理,如:可以直接過濾空值的行
2.在最后結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
3.不同數據類型關聯產生數據傾斜
情形:
比如用戶表中 user_id 字段為 int,log 表中 user_id 字段既有 string 類型也有int類型。
當按照 user_id 進行兩個表的 Join 操作時,處理此特殊值的reduce耗時;只有一個reduce任務,默認的Hash操作會按int型的id來進行分配,這樣會導致所有string類型id的記錄都分配到一個Reducer中。
解決方式:
把數字類型轉換成字符串類型。
4.空值分布產生數據傾斜
解決方案:
1.把空值的key變成一個字符串加上一個隨機數,把傾斜的數據分到不同的reduce上,由於null值關聯不上,處理后並不影響最終的結果。
2.對於異常值如果不需要的話,最好是提前在 where 條件里過濾掉,這樣可以使計算量大大減少。
3.實踐中,可以使用 case when 對空值賦上隨機值。此方法比直接寫 is not null 更好,因為前者 job 數為 1,后者為 2.
4.如果上述的方法還不能解決,比如當有多個JOIN的時候,建議建立臨時表,然后拆分HIVE SQL語句。
5.對於sql語句產生數據傾斜
解決方案:
1.選用join key分布最均勻的表作為驅動表。做好列裁剪和filter操作,以達到兩表join的時候,數據量相對變小的效果。
2.大小表join:使用map join讓小的維度表(1000條以下的記錄條數)先進內存。在Map端完成reduce.
5. 開啟數據傾斜時負載均衡
set hive.groupby.skewindata=true;
思想:就是先隨機分發並處理,再按照 key group by 來分發處理
操作:當選項設定為 true,生成的查詢計划會有兩個 MRJob。
第一個 MRJob 中,Map 的輸出結果集合會隨機分布到 Reduce 中,每個 Reduce 做部分聚合操作,並輸出結果,這樣處理的結果是相同的 GroupBy Key 有可能被分發到不同的Reduce 中,從而達到負載均衡的目的;
第二個 MRJob 再根據預處理的數據結果按照 GroupBy Key 分布到 Reduce 中(這個過程可以保證相同的原始 GroupBy Key 被分布到同一個 Reduce 中),最后完成最終的聚合操作。
總結:它使計算變成了兩個 mapreduce,先在第一個中在 shuffle 過程 partition 時隨機給 key 打標記,使每個 key 隨機均勻分布到各個reduce 上計算,但是這樣只能完成部分計算,因為相同 key 沒有分配到相同 reduce 上。所以需要第二次的 mapreduce,這次就回歸正常 shuffle,但是數據分布不均勻的問題在第一次 mapreduce 已經有了很大的改善,因此基本解決數據傾斜。因為大量計算已經在第一次mr 中隨機分布到各個節點完成。
21. 描述數據中的null在hive底層如何存儲?
null在hive底層默認是用"\N"來存儲的
22. hive中的壓縮格式RCFile、TextFile、SequenceFile各有什么區別?
TextFile:默認格式,數據不做壓縮,磁盤開銷大,數據解析開銷大
SequenceFile:Hadoop API提供的一種二進制文件支持,使用方便,可分割,支持三種壓縮,NONE,RECORD,BLOCK
RCFILE:是一種行列存儲相結合的方式。首先,將數據按行分塊,保證同一個record在同一個塊上,避免讀一個記錄讀取多個block。
其次,塊數據列式存儲,有利於數據壓縮和快速的列存取。數據加載的時候性能消耗大,但具有較好的壓縮比和查詢響應。
23. hive如何優化?(要背過)
1. 表的優化(小表與大表)
Hive默認第一個(左面的)表是小表,然后將其存放到內存中,然后去與第二張表進行比較
現在優化后小表前后無所謂
join優化:盡量將小的表放在join的左邊,如果一個表很小可以采用map join.
2. 表的優化(大表與大表)
針對於空值,可以將空值隨機設置一個不影響結果的值
將來reduce的時候可以分區到不同的reduce,減少壓力
3. mapside聚合
簡單來說,即再Reduce階段完成join,容易發生數據傾斜;可以用MapJoin把小表全部加載到內存在map端進行join,避免reducer處理。
默認情況下,Map階段同一個key數據分發給一個reduce,當一個key數據過大時就傾斜了。
並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最后在Reduce端得出最終結果。
(1)開啟Map端聚合參數設置
是否在Map端進行聚合,默認為True
hive.map.aggr = true
(2)在Map端進行聚合操作的條目數目
hive.groupby.mapaggr.checkinterval = 100000
(3)有數據傾斜的時候進行負載均衡(默認是false)
hive.groupby.skewindata = true
當選項設定為true,生成的查詢計划會有兩個MR Job.
分兩次進行mapreduce,第一次隨機分 獲取中間結果;第二次正常分,獲取最終結果。
4. Count(Distinct)
防止所有的數據都分到一個Reduce上面
首先使用Group By對數據進行分組,然后再統計
5. 防止笛卡爾乘積
行列過濾(列裁剪):
當表關聯的時候,優先使用子查詢對表的數據進行過濾,這樣前面表關聯數據就是少的,減少關聯的次數。
案例實操:
1.測試先關聯兩張表,再用where條件過濾。
select o.id
from bigtable b
join ori o
on o.id = b.id
where o.id <= 10;
2.通過子查詢后,再關聯表
select b.id
from bigtable b
join
(
select id
from ori
where id <= 10
) o
6. 工作上經常用到的hivesql技巧
1.多表關聯時要多用union all,多個union all會優化成一個job
2.修改表結構要用replace columns
,使用add columns數據為空,這時因為元數據庫沒有更新
3.注意Hive中NULL和' '的區別,不管哪一種作相加的時候都會變成null
4.去列參數set hive.support.quoted.identifiers = none;
5.查詢切記加limit
備注:
union會自動壓縮多個結果集合中的重復結果,而union all則將所有的結果全部顯示出來,不管是不是重復。
7. 排序優化
order by一個reduce效率低,distribute by + sort by也可以實現全局排序
8. 使用分區
查詢時可減少數據的檢索,從而節省時間
9. 多采用分桶技術
10. 結合實際環境合理設置Map數
1.通常情況下,作業會通過input的目錄產生一個或者多個map任務。
主要的決定因素有:input的文件總個數,input的文件大小,集群設置的文件塊大小
2.map數不是越多越好,如果一個任務有很多小文件(遠遠小於塊大小128M),則每個小文件也會被當作一個塊,用一個map任務來完成,而一個map任務啟動和初始化的時間遠遠大於邏輯處理的時間,就會造成很大的資源浪費。而且同時可執行的map數是受限的。解決這個問題需要減少map數。
3.並不是每個map處理接近128m的文件塊就是完美的;比如有一個 127m 的文件,正常會用一個 map 去完成,但這個文件只有一個或者兩個小字段,卻有幾千萬的記錄,如果 map 處理的邏輯比較復雜,用一個 map 任務去做,肯定也比較耗時。解決這個問題需要增加map數。
11.合並大量小文件
在Map執行前合並小文件,可以減少Map數:CombineHiveInputFormat 具有對小文件進行合並的功能(系統默認的格式)。HiveInputFormat 沒有對小文件合並功能。
12.設置合理的Reduce數
reduce個數也並不是越多越好
1.過多的啟動和初始化 Reduce 也會消耗時間和資源;
2.有多少個 Reduce,就會有多少個輸出文件,如果生成了很多個小文件,那么如果這些小文件作為下一個任務的輸入,則也會出現小文件過多的問題;
3.在設置Reduce個數的時候也需要考慮這兩個原則:處理大數據量利用合適的 Reduce 數;使單個 Reduce 任務處理數據量大小要合適;
13.開啟map端combiner(不影響最終業務邏輯)
set hive.map.aggr=true;
14.中間結果壓縮
設置map端輸出、中間結果壓縮
(不完全是解決數據傾斜的問題,但是減少了IO讀寫和網絡傳輸,能提高很多效率)
24. hive分桶管理
1. 原理
與MR的HashPartition的原理一摸一樣
MR中:按照key的hash值去模除以reducetask的個數
HIVE中:按照分桶字段的hash值去模除以分桶的個數
2. hive分桶的作用
方便抽樣、提高join查詢效率
3. hive分桶和分區的作用
分桶表和分區表的桶數和分區數的決定機制:
分桶表的個數:由用戶HQL語句所設置的reduce Task的個數決定
表的分區個數:也能由用戶定義,也能由程序自動生成,分區是可以動態增長的。
個數區別:
•分桶表一經決定,就不能更改,所以如果有要改變桶數,要重新插入分桶數據;
•分區數是可以動態增長的。如log日志,一天存一個分區
4. hive分桶操作
4.1創建分桶表
create table bck_student(
id int,
name string,
sex string,
age int,
department string
) clustered by(sex) into 2 buckets row format delimited fields
terminated by ",";
4.2 創建臨時表並導入數據
create table student(
id int,
name string,
sex string,
age int,
department string
) row format delimited fields terminated by ",";
load data local inpath "/home/hadoop/student.dat" into table student;
select * from student
4.3 從臨時表中分桶查詢出來的數據insert到分桶的空表里
# 開啟分桶
set hive.enforce.bucketing=true;
set mapreduce.job.reduces=2;
# 注意上面的set mapreduce.job.reduces的數量要和分桶數量一樣
insert into table bck_student select id,name,sex,age,department from student distribute by sex;
4.4 對分桶數據進行抽樣查詢
select * from bck_student tablesample(bucket 1 out of 2 on sex)
# select * from bck_student tablesample(0.1 percent);