hive常見的幾種優化手段

来源:https://www.cnblogs.com/qinshifu/archive/2018/09/09/9615255.html
-Advertisement-
Play Games

Hive調優的幾個入手點: Hive是基於Hadoop框架的,Hadoop框架又是運行在JVM中的,而JVM最終是要運行在操作系統之上的,所以,Hive的調優可以通過如下幾個方面入手: 操作系統調優 - Hadoop主要的操作系統是Linux,Linux系統調優包括文件系統的選擇、cpu的調度、記憶體 ...


Hive調優的幾個入手點:

Hive是基於Hadoop框架的,Hadoop框架又是運行在JVM中的,而JVM最終是要運行在操作系統之上的,所以,Hive的調優可以通過如下幾個方面入手:

  • 操作系統調優

- Hadoop主要的操作系統是Linux,Linux系統調優包括文件系統的選擇、cpu的調度、記憶體構架和虛擬記憶體的管理、IO調度和網路子系統的選擇等等。

  • JVM的調優

- JVM調優主要包括堆棧的大小、回收器的選擇等等。

  • Hadoop參數調優

- Hive查詢sql性能調優。

Hive總體調優:

  • join連接時的優化

- 當多個表進行查詢時,從左到右表的大小順序應該是從小到大(hive在對每行記錄操作時會把其他表先緩存起來,直到掃描最後的表進行計算)。

- 當可以使用left semi join 語法時不要使用inner join,前者效率更高(對於左表中指定的一條記錄,一旦在右表中找到立即停止掃描)。

  • 在where子句中增加分區過濾器。
  • 使用記憶體表(mapjoin)

- 如果所有表中有一張表足夠小,則可置於記憶體中,這樣在和其他表進行連接的時候就能完成匹配,省略掉reduce過程。

- 記憶體連接查詢 mapjoin:

在map端完成join操作,不需要用reduce,基於記憶體做join,屬於優化操作。

在map端把小表載入到記憶體中,然後讀取大表,和記憶體中的小表完成連接操作。其中使用了分散式緩存技術。

不消耗集群的reduce資源(適用於reduce相對緊缺),減少了reduce操作,加快程式執行,降低網路負載。

占用部分記憶體,所以載入到記憶體中的表不能過大,因為每個計算節點都會載入一次。

- 基礎語法

select /*+mapjoin(載入入記憶體的表別名)*/ 表別名1.列1,表別名1.列2,表別名2.列3...

from (select 列1,列2,列3... from 表1) 表別名1

join (select 列1,列2,列3... from 表2) 表別名2

on 表別名1.列1=表別名2.列1

  • 同一種數據的多種處理

- 從一個數據源產生的多個數據聚合,無需每次聚合都需要重新掃描一次。

例如,從employee中取出數據分別插入student和person兩張表。

低效的寫法: insert overwrite table student select * from employee; insert overwrite table person select * from employee;

高效的寫法: from employee insert overwrite table student select * insert overwrite table person select *

  • 使用limit子句

- limit子句用於限制返回數據的結果集大小。

- limit子句通常位於所有查詢的結尾處。

- limit子句示例:

select t1.*,t2.score,t3.score from Student t1

inner join SC t2 on t1.Sid = t2.Sid and t2.Cid = '01'

inner join SC t3 on t1.Sid = t3.Sid and t3.Cid = '02'

where t2.score > t3.score limit 1;

  • 設置多個reduce並開啟併發執行

- 某個job任務中可能包含眾多的階段,其中某些階段沒有依賴關係可以併發執行,開啟併發執行後job任務可以更快的完成。

- 開啟併發執行:set hive.exec.parallel=true

  • hive的使用禁忌:

- 當表為分區表時,where字句後沒有分區欄位和限制時,不允許執行。

- 能使用sort by排序的,不要使用order by,當使用order by語句時,請使用limit欄位,因為order by只會產生一個reduce任務。

- 限制笛卡爾積的查詢。

Hive排序調優 

  • 假設我們有一張數據量很大的表,表結構如下

我們希望對裡面多個欄位分組排序,sql如下:

select t1.ip,t1.logtime,t1.logmessage,t1.logstatus from

(select ip,logtime,logmessage,logstatus,logsize from logfile

order by ip,logtime,logmessage,logstatus,logsize asc) t1

group by t1.ip,t1.logtime,t1.logmessage,t1.logstatus limit 100;

很明顯,這條sql的reduce階段只有一個reduce, 這是因為ORDER BY是全局排序,hive只能通過一個reduce進行排序;

優化方案:我們可以使用distribute by和sort by配合使用,來完成排序,這樣可以充分利用hadoop資源, 在多個reduce中局部排序,修改後的sql:

select t1.ip,t1.logtime,t1.logmessage,t1.logstatus from

(select ip,logtime,logmessage,logstatus,logsize from logfile

distribute by ip,logtime,logmessage,logstatus

sort by logsize asc) t1

group by t1.ip,t1.logtime,t1.logmessage,t1.logstatus;

Map數量調優

  • 通常情況下,作業會通過input的目錄(數據塊的分佈)產生一個或者多個map任務。

- 主要的決定因素有: input的文件總個數,input的文件大小,集群設置的文件塊大小。

  • map分佈實例

- 假設input目錄下有1個文件a,大小為780M,那麼hadoop會將該文件a分隔成7個塊(6個128m的塊和1個12m的塊),從而產生7個map數。

- 假設input目錄下有3個文件a,b,c,大小分別為10m,20m,130m,那麼hadoop會分隔成4個塊(10m,20m,128m,2m),從而產生4個map數。

  • 是不是map數越多越好?

- 如果一個任務有很多小文件(遠遠小於塊大小128m),則每個小文件也會被當做一個塊,用一個map任務來完成。

- 一個map任務啟動和初始化的時間遠遠大於邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執行的map數是受限的。 所以map不是越多越好,而是分塊大小越接近128越好。 這種情況可以合併小文件,降低map數量。

  • 是不是所有分塊大小越接近128越好?

- 比如有一個127m的文件,正常會用一個map去完成,但這個文件只有一個或者兩個小欄位,卻有幾千萬的記錄,如果map處理的邏輯比較複雜,用一個map任務去做,肯定也比較耗時。 這種情況可以拆分文件,添加map數量。

  • 所以,map數量的多少,要根據業務邏輯具體調整,並通過文件大小調節map數量。
  • hive合併小文件,減少map數量的設置參數(根據實際情況調整)

- set mapred.max.split.size;

- set mapred.min.split.size.per.node;

- set mapred.min.split.size.per.rack;

- set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

  • hive拆分大文件,增加map數量

- set mapred.reduce.tasks

Reduce數量調優

  • 是不是reduce數越多越好?

- 同map一樣,啟動和初始化reduce也會消耗時間和資源。 有多少個reduce,就會有多少個輸出文件,如果生成了很多個小文件,那麼如果這些小文件作為下一個任務的輸入,則也會出現小文件過多的問題。

  • 同樣,在設置reduce個數的時候也需要考慮這兩個原則:

- 使大數據量利用合適的reduce數;

- 使單個reduce任務處理合適的數據量。

  • 預設reduce數量

- hive.exec.reducers.bytes.per.reducer(每個reduce任務處理的數據量,預設為1000^3=1G)

- 計算reducer數的公式:總輸入數據量/上述參數,如果reduce的輸入(map的輸出)總大小不超過1G,那麼只會有一個reduce任務

  • 調整reduce數量的方法

- set hive.exec.reducers.bytes.per.reducer=500000000(動態計算)

- set mapred.reduce.tasks = 15(可直接設置數量)

  • 很多時候我們會發現任務中不管數據量多大,不管有沒有設置調整reduce個數的參數,任務中一直都只有一個reduce任務,出現這種情況的原因:

- 沒有group by的彙總或用了Order by(常見)

- 有笛卡爾積

Sql具體優化示例 

  • 關於子查詢

- 過濾子查詢中的數據,減少子查詢中的數據量。

- 對於分區表要加分區。

- 子查詢只選擇需要使用到的欄位。

- 低效寫法:

select a.user_id from dwd.dwd_d_res_mb_five_imei a

inner join dwd.dwd_d_prd_cm_user_info b on a.user_id=b.user_id

where a.service_type='4G' and b.service_type='4G'and

concat(a.month_id,a.day_id)='20160626‘ and b.day_id='26';

- 高效寫法:

select a.user_id from

(select user_id from dwd.dwd_d_res_mb_five_imei a

where concat(a.month_id,a.day_id)='20160626' and a.service_type='4G') a

inner join

(select user_id from dwd.dwd_d_prd_cm_user_info b

where b.day_id='26' and b.service_type='4G') b on a.user_id=b.user_id;

  • 合理使用union all

- 子查詢中union all部分個數大於2,或者每個union all部分數據量很大,應該拆分多段insert。這樣執行時間能提升50%。

- 低效寫法:

insert overwite table tablename partition (day_id= ....)

select ..... from (

select ... from A union all

select ... from B union all

select ... from C) R

where ...;

- 高效寫法:

insert into table tablename partition (day_id= ....)

select .... from A

WHERE ...;

insert into table tablename partition (day_id= ....)

select .... from B

WHERE ...;

insert into table tablename partition (day_id= ....)

select .... from C

WHERE ...;

  • 不要使用count(distinct),避免數據傾斜

- count(distinct)操作會造成數據傾斜,效率較低,數據量一多,極容易出問題。

- 低效寫法:

select a, count(distinct b) as c from tbl group by a;

- 高效寫法:

select a, count(1) as c from (select a, b from tbl group by a, b) t group by a;

  • hive中沒有in/exists (not),使用LEFT OUTER JOIN或LEFT SEMI JOIN

- LEFT OUTER JOIN寫法:

SELECT a.key, a.value FROM a LEFT OUTER JOIN b ON (a.key = b.key) WHERE b.key is not NULL and b.key<>’’;

- LEFT SEMI JOIN更為高效,

LEFT SEMI JOIN 的限制是,JOIN 子句中右邊的表只能在 ON 子句中設置過濾條件,在 WHERE 子句、SELECT 子句或其他地方過濾都不行。

  • 減少job數

- 在開發過程中,會生成多餘Job不夠高效比如查詢某網站日誌中訪問過頁面a和頁面b的用戶數量

- 低效的寫法是面向明細的,先取出看過頁面a的用戶,再取出看過頁面b的用戶,然後取交集,sql如下:

select count(1) from

(select distinct user_id from logs where page_name = 'a') a

inner join

(select distinct user_id from logs where page_name = 'b') b

on a.user_id = b.user_id;

- 這個sql會產生2個求子查詢的Job,一個用於關聯的Job,還有一個計數的Job,一共有4個Job。

- 高效思路是用group by替代join,更加符合M/R的模式,而且生成了一個完全不帶子查詢的sql,只需要用一個Job就能跑完:

select count(1) from logs

group by user_id

having (count(case when page_name = 'a' then 1 end) > 0

and count(case when page_name = 'b' then 1 end) > 0)

其它優化註意事項

  • 查詢sql中避免複雜邏輯,原子化操作,查詢sql包含複雜邏輯的,可以拆分成中間表。
  • join連接key為空時,空的key都hash到一個reduce上去了。高效做法是把空的key和非空的key做區分,空的key不做join操作。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第1章 實時同步 1.1 什麼是實時同步 實時同步是一種只要當前目錄觸發事件,就馬上同步到遠程的目錄。rsync 1.2 為什麼要實時同步web->nfs->backup 保證數據的連續性(定時任務是以分鐘為單位的) 減少人力維護成本 1.3 實時同步工具的選擇 inotify+RSYNC(x) s ...
  • 使用Centos7虛擬機時,想要從主機傳一些文件到虛擬機,需要使用FTP傳輸,在主機上裝上的CuteFTP的軟體,對虛擬機進行配置。 1,首先,要保證虛擬機能夠上網 一般裝好虛擬機後,只要主機連了網,虛擬機也是有網的,這裡簡單的介紹一下吧。 首先設置網路連接模式。點擊虛擬機 - >設置 - >網路適 ...
  • 為centos配置網路 (1)第一步 點開虛擬機的設置,如下圖做相關的設置: 網路連接要選擇橋接模式,其他的勾選就按照上圖的即可,勾選完成點擊確定。 (2)第二步 點擊VMware的編輯選項,找到“虛擬網路編輯器”,打開它。如下圖更改。 VMhet0勾選橋接模式。一定要註意,橋接到後面的下拉框可能有 ...
  • 1.DNS簡介 DNS(功能變數名稱系統)即domain name server, 將主機名與IP簡歷關聯,使用戶可以通過主機名(功能變數名稱)訪問網路中的主機.對於伺服器主機,即使伺服器的IP地址改變了,只要將新的IP地址與功能變數名稱關聯,而不是通知用戶新的功能變數名稱. DNS 通常採用一個或多個為某些域認證的集中伺服器部署 ...
  • 一、環境 三台centos機器 二、軟體及容器準備 1.安裝docker環境 本例安裝 docker-ce版本,repo源為docker-ce.repo文件,拷貝到 /etc/yum.repos.d下 yum install -y docker-ce 2.下載相關鏡像 本例需要一下鏡像,為了集群創建 ...
  • 一、ubuntu 配置虛擬主機 方法一:添加埠號 第一步進入 /etc/apache2/sites-available/ 目錄,將 000-default.conf 複製一份到當前目錄下並重命名,然後開始編輯。命令和編輯內容如下 1 cd /etc/apache2/sites-available/ ...
  • 1.SVN服務實戰 1) 什麼是SVN(Subversion)? Svn(subversion)是近年來崛起的非常優秀的版本管理工具,與CVS管理工具一樣,SVN是一個跨平臺的開源的版本控制系統。Svn版本管理工具管理著隨時間改變的各種數據。這些數據放置在一個中央資料檔案庫(repository)中 ...
  • 對於新部署的機器,需要做一些基本的調優操作,以更改一些預設配置帶來的性能問題 1 修改打開文件數 root@mysql:/data/tools/db# vim /etc/security/limits.conf root@mysql:/data/tools/db# cd /etc/security/ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...