打怪升级之小白的大数据之旅(六十九)<Hive旅程第十站:Hive的优化>
打怪升級之小白的大數據之旅(六十九)
Hive旅程第十站:Hive的優化
上次回顧
上一章介紹了Hive的壓縮與存儲格式,本章節是Hive的一起其他優化方法
Fetch抓取
-
Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算
-
從hive學到了現在,大家有沒有這個疑問,為什么使用select * from 表名的時候,hive不走MR程序呢?而使用select count(*) from 表名會執行MR程序?
-
SELECT * FROM 表名;在這種情況下,Hive可以簡單地讀取該表對應的存儲目錄下的文件,然后輸出查詢結果到控制臺(因為表是通過元數據做映射的,實際表它就是一個文件夾)
-
在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改為more以后,在全局查找、字段查找、limit查找等都不走mapreduce
以我們的emp員工表查詢舉例:
- 把hive.fetch.task.conversion設置成none,然后執行查詢語句,都會執行mapreduce程序# 設置抓取為none set hive.fetch.task.conversion=none; select *from emp; select ename from emp; select ename from emp limit 3;
- 把hive.fetch.task.conversion設置成more,然后執行查詢語句,如下查詢方式都不會執行mapreduce程序# 設置抓取為none set hive.fetch.task.conversion=none; select *from emp; select ename from emp; select ename from emp limit 3;
本地模式
- 在實際開發中,大多數的Hadoop Job是需要Hadoop提供的完整的可擴展性來處理大數據集的
- 不過,有時Hive的輸入數據量是非常小的。在這種情況下,為查詢觸發執行任務消耗的時間可能會比實際job的執行時間要多的多
- 對于大多數這種情況,Hive可以通過本地模式在單臺機器上處理所有的任務。對于小數據集,執行時間可以明顯被縮短
- 我們可以通過設置hive.exec.mode.local.auto的值為true,來讓Hive在適當的時候自動啟動這個優化
- 具體參數說明如下:set hive.exec.mode.local.auto=true; //開啟本地mr //設置local mr的最大輸入數據量,當輸入數據量小于這個值時采用local mr的方式,默認為134217728,即128M set hive.exec.mode.local.auto.inputbytes.max=50000000; //設置local mr的最大輸入文件個數,當輸入文件個數小于這個值時采用local mr的方式,默認為4 set hive.exec.mode.local.auto.input.files.max=10;
還是以員工表emp舉例:
開啟本地模式,并執行查詢語句
set hive.exec.mode.local.auto=true; select * from emp cluster by deptno; -- 用時:Time taken: 1.328 seconds, Fetched: 14 row(s)關閉本地模式,并執行查詢語句
set hive.exec.mode.local.auto=false; select * from emp cluster by deptno; -- 用時:Time taken: 20.09 seconds, Fetched: 14 row(s)表的優化
小表與大表的Join
- 在以前我們寫SQL時,通常有個習慣,就是小表放左邊,大表放后面,這是因為將key相對分散,并且數據量小的表放在join的左邊,這樣可以有效減少內存溢出錯誤發生的幾率
- 新版的hive已經對小表JOIN大表和大表JOIN小表進行了優化。小表放在左邊和右邊已經沒有明顯區別
- 具體的優化是因為下面這個配置參數,默認是true,如果我們設置為false,那么我們將小表放左邊和放右邊,效率就會有明顯的不同set hive.auto.convert.join = true;
大表與大表的Join
空Key過濾
實際開發過程中,數據集并不是都是有數據的,常常會遇到NULL字段,但是根據業務不同,我們在大表間的合并時,對NULL的處理也有所不同,根據業務不同可以分為下面兩種情況
- 不需要字段為Null
- 此時我們可以先過濾Null然后再進行Join,這樣還可以避免笛卡爾積的發生
- 非 inner join(因為inner join 默認會獲取非Null數據)
- 此時我們先Join再過濾Null
案例(測試數據可以后臺聯系我)
- 有時join超時是因為某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠
- 此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據
- 我們需要在SQL語句中進行過濾。例如key對應的字段為空
進行示例前,我們先開啟歷史服務器,便于我們觀察
-
配置mapred-site.xml
# 配置歷史服務器 <property> <name>mapreduce.jobhistory.address</name> <value>hadoop102:10020</value> </property> <property><name>mapreduce.jobhistory.webapp.address</name><value>hadoop102:19888</value> </property> -
啟動歷史服務器
sbin/mr-jobhistory-daemon.sh start historyserver -
查看jobhistory
http://hadoop102:19888/jobhistory
測試數據(這個數據是很久之前模擬用戶使用搜索引擎時的記錄)
# 總共大概100萬條,我只展示一部分 vim /opt/module/hive/dbdata/nullid\N 20111230000005 57375476989eea12893c0c3811607bcf 奇藝高清 1 1 http://www.qiyi.com/ \N 20111230000005 66c5bb7774e31d0a22278249b26bc83a 凡人修仙傳 3 1 http://www.booksky.org/BookDetail.aspx?BookID=1050804&Level=1 \N 20111230000007 b97920521c78de70ac38e3713f524b50 本本聯盟 1 1 http://www.bblianmeng.com/ \N 20111230000008 6961d0c97fe93701fc9c0d861d096cd9 華南師范大學圖書館 1 1 http://lib.scnu.edu.cn/ \N 20111230000008 f2f5a21c764aebde1e8afcc2871e086f 在線代理 2 1 http://proxyie.cn/ \N 20111230000009 96994a0480e7e1edcaef67b20d8816b7 偉大導演 1 1 http://movie.douban.com/review/1128960/ \N 20111230000009 698956eb07815439fe5f46e9a4503997 youku 1 1 http://www.youku.com/ \N 20111230000009 599cd26984f72ee68b2b6ebefccf6aed 安徽合肥365房產網 1 1 http://hf.house365.com/ \N 20111230000010 f577230df7b6c532837cd16ab731f874 哈薩克網址大全 1 1 http://www.kz321.com/ \N 20111230000010 285f88780dd0659f5fc8acc7cc4949f2 IQ數碼 1 1 http://www.iqshuma.com/ \N 20111230000010 f4ba3f337efb1cc469fcd0b34feff9fb 推薦待機時間長的手機 1 1 http://mobile.zol.com.cn/148/1487938.html-
創建空id表
// 創建空id表 create table nullidtable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t'; -
加載空id數據到空id表中
- 測試不過濾空id
- 測試過濾空id
空key轉換
- 有時雖然某個key為空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中
- 此時我們可以表a中key為空的字段賦一個隨機的值,使得數據隨機均勻地分布到不同的reducer上
不隨機分布空null值
-- 設置5個reduce個數 set mapreduce.job.reduces = 5; -- JOIN兩張表 insert overwrite table jointable select n.* from nullidtable n left join bigtable b on n.id = b.id;通過歷史服務器,我們可以發現出現了數據傾斜,第一條的執行時間要遠遠大于其他
使用隨機分布空null值
下圖可以發現,我們剛才的數據傾斜基本上得到了控制(數據傾斜不可能完全消除)
Group By
默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了,如下圖
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最后在Reduce端得出最終結果
我們可以通過開啟Map端聚合來減少負載均衡
(1)是否在Map端進行聚合,默認為True set hive.map.aggr = true (2)在Map端進行聚合操作的條目數目 set hive.groupby.mapaggr.checkinterval = 100000 (3)有數據傾斜的時候進行負載均衡(默認是false) set hive.groupby.skewindata = true開啟Map端聚合來減少負載均衡原理:
- 當選項設定為 true,生成的查詢計劃會有兩個MR Job
- 第一個MR Job中,Map的輸出結果會隨機分布到Reduce中,每個Reduce做部分聚合操作,并輸出結果
- 這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;
- 第二個MR Job再根據預處理的數據結果按照Group By Key分布到Reduce中(這個過程可以保證相同的Group By Key被分布到同一個Reduce中),最后完成最終的聚合操作
Count(Distinct) 去重統計
- 數據量小的時候無所謂,數據量大的情況下,由于COUNT DISTINCT操作需要用一個Reduce Task來完成
- 這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成
- 一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換,但是需要注意group by造成的數據傾斜問題
笛卡爾積
笛卡爾積在Hadoop介紹過了,我們盡量避免笛卡爾積,join的時候不加on條件,或者無效的on條件,Hive只能使用1個reducer來完成笛卡爾積
行列過濾
- 列處理:在SELECT中,只拿需要的列,如果有,盡量使用分區過濾,少用SELECT *。
- 行處理:在分區剪裁中,當使用外關聯時,如果將副表的過濾條件寫在Where后面,那么就會先全表關聯,之后再過濾
- 在HQL中,當我們使用了where,底層會優先執行過濾條件,通常稱這個操作為謂詞下推
- 意思就是當sql語句不是很長的時候,它會將HQL語句中的where過濾條件先執行再進行關聯操作,第二種相當于手動進行謂詞下推操作,子查詢進行了過濾之后,在進行聯表操作
分區和分桶
使用了分區表和分桶表可以大大提高我們的查詢效率,具體的創建和使用方法我在單獨的那一章介紹過了:https://blog.csdn.net/Li_G_yuan/article/details/117395941?spm=1001.2014.3001.5501
并行執行&JVM重用
JVM重用
- JVM重用我在Hadoop優化也講過了,就不再重復了
并行執行 - 默認情況下,Hive一次只會執行一個階段
- 不過,某個特定的job可能包含眾多的階段,而這些階段可能并非完全互相依賴的,也就是說有些階段是可以并行執行的
- 這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以并行執行,那么job可能就越快完成
- 在hive中,通過設置參數hive.exec.parallel值為true,就可以開啟并發執行。不過,在共享集群中,需要注意下,如果job中并行階段增多,那么集群利用率就會增加
當然,得是在系統資源比較空閑的時候才有優勢,否則,沒資源,并行也起不來
嚴格模式
分區表不使用分區過濾
- 將hive.strict.checks.no.partition.filter設置為true時,對于分區表,除非where語句中含有分區字段過濾條件來限制范圍,否則不允許執行。
- 換句話說,就是用戶不允許掃描所有分區。進行這個限制的原因是,通常分區表都擁有非常大的數據集,而且數據增加迅速。
- 沒有進行分區限制的查詢可能會消耗令人不可接受的巨大資源來處理這個表
使用order by沒有limit過濾
- 將hive.strict.checks.orderby.no.limit設置為true時,對于使用了order by語句的查詢,要求必須使用limit語
- 因為order by為了執行排序過程會將所有的結果數據分發到同一個Reducer中進行處理
- 強制要求用戶增加這個LIMIT語句可以防止Reducer額外執行很長一段時間
笛卡爾積判定
- 將hive.strict.checks.cartesian.product設置為true時,會限制笛卡爾積的查詢。hive.strict.checks.cartesian.product
執行計劃
實際開發中,我們要善用執行計劃來查看我們的HQL語句,這樣可以大大減少因為語法問題導致時間的浪費
語法格式
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query (1)查看下面這條語句的執行計劃 hive (default)> explain select * from emp; hive (default)> explain select deptno, avg(sal) avg_sal from emp group by deptno; (2)查看詳細執行計劃 hive (default)> explain extended select * from emp; hive (default)> explain extended select deptno, avg(sal) avg_sal from emp group by deptno;總結
Hive的所有知識點到這里就結束了,下一章是一綜合案例,綜合案例完畢我會總結一下整個Hive的內容
總結
以上是生活随笔為你收集整理的打怪升级之小白的大数据之旅(六十九)<Hive旅程第十站:Hive的优化>的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大学生的移动开发之惑
- 下一篇: 解决react antd design