hive中控制文件生產個數


在有些時候,想要控制hql執行的mapper,reducer個數,reducer設置過少,會導致每個reducer要處理的數據過多,這樣可能會導致OOM異常,如果reducer設置過多,則會導致產生很多小文件,這樣對任務的執行以及集群都不太好.通常情況下這兩個參數都不需要手動設置,Hive會根據文件的大小和任務的情況自動計算,但是某些特殊情況下可能需要進行調優,下面列舉兩個常用的調優場景看看這兩個參數在調優的時候都是怎么用的:

方法一:設置reducer個數

reducer個數最直接的影響是hql執行完之后生成的文件個數,假設你的任務有n個reducer,那么最后可能會生成的文件肯定至少有n個,前提是你沒有設置合並小文件,這個有什么用處呢?最簡單的一個用處是我們在hive里面經常會調第三方接口來獲取數據,例如解密之內的,假設接口不限速,我們在udf里面調接口的時候會發現特別慢,感覺直接select很快,但是把查詢結果insert到一個表保存就很慢,這個原因就在於數據請求線程太少了。
在hadoop里面,一個文件至少會起一個mapper,如果你的文件很小(默認1G起一個mapper),那就完了,整個任務就一直是一個個來請求接口的,所以非常的慢。那如果想加快接口的調用呢?其實也簡單,把文件分成幾個小文件,假設分成了10個小文件,那么再次調接口就會快很多了,10線程和單線程的差別還是非常大的。
具體的語句也就兩句話,記住,划分小文件還得保證每個文件盡量大小一樣。

  1. set mapred.reduce.tasks=50;
  2. insert into table xxx
  3. select
  4. *
  5. from
  6. xxx
  7. distribute by rand();

 

方法二:設置每個reducer處理的數據

 

  1. set hive.exec.reducers.bytes.per.reducer=5120000000;
  2. insert into table xxx
  3. select
  4. *
  5. from
  6. xxx
  7. distribute by rand();

備注:第一個set設置的就是最后你要生成的文件個數,后面的distribute by rand()保證了記錄隨機分配到50個文件,不管里數據量有多小,最后這50個文件的大小應該是一致的.

動態分區產生小文件

有些場景會產生大量的文件,比如動態分區插入,或者兩個比較大的表做join,對於大表做join,我沒有細測,但是我發現我用一個很小的表(大概70M),去join一個很大的表(大概400G),由於Hive在處理小表join大表的時候會做優化,左邊的表會都加載到內存里面,然后分發到各個節點和大表做join,這樣最后就會在大表所在的節點產生最終的結果,后果就是會原來大表的那些文件現在都變成小文件了,小文件太多其實對性能還是有影響的,這個其實可以最后用一個reducer來合並小文件。
主要說一下動態分區產生小文件問題,這是個很有意思的問題,動態分區好用,但是為啥會產生這么多小文件。原因就在於,假設動態分區初始有N個mapper,那么最后生成了m個分區,最終會有多少個文件生成呢?答案是N*m,是的,每一個mapper會生成m個文件,就是每個分區都會對應一個文件,這樣的話你算一下。所以小文件就會成倍的產生。怎么解決這個問題,通常處理方式也是像上面那樣,讓數據盡量聚到一個reducer里面,因為有時候雖然動態分區不會產生reducer,但是也就意味着最后沒有進行文件合並,我們也可以用distribute by rand()這句來保證數據聚類到相同的reducer。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM