1. 程式人生 > >hive兩大表關聯優化試驗

hive兩大表關聯優化試驗

呼叫結果(call_result)與銷售歷史(sale_history)的join優化:
CALL_RESULT: 32億條/444G SALE_HISTORY:17億條/439G

  • 原邏輯
    Map: 3255 Reduce: 950 Cumulative CPU: 238867.84 sec HDFS Read: 587550313339 HDFS Write: 725372805057 SUCCESS 28.1MIN

  • 開啟中間結果壓縮
    set hive.exec.compress.intermediate=true;
    set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec

    Map: 3255 Reduce: 950 Cumulative CPU: 268479.06 sec HDFS Read: 587548211067 HDFS Write: 725372805057 SUCCESS 31.6MIN
    從結果看cpu的耗時增加,這是壓縮解壓縮過程的消耗;HDFS讀取量略有減少,可能是因為源表是RCFile儲存,本身已經壓縮導致,因此整體時間上沒有明顯減少。

  • 開啟中間和最終壓縮
    set hive.exec.compress.intermediate=true;
    set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
    set hive.exec.compress.output=true;
    set mapred.output.compression.codec=org.apache.hadoop.io.compress.GZipCodec

    Map: 3255 Reduce: 950 Cumulative CPU: 264034.27 sec HDFS Read: 587546058107 HDFS Write: 136021543504 SUCCESS 24.7MIN
    從結果看HDFS write明顯減少近6倍,整體執行時間有所降低

  • 設定map數量減少一倍
    set mapred.max.split.size=512000000
    Map: 1684 Reduce: 950 Cumulative CPU: 191656.39 sec HDFS Read: 585689265249 HDFS Write: 725372805057 SUCCESS 22.9MIN


    map數減少一倍後,消耗cpu資源減少;整體執行時間略有下降

  • 只開啟JVM重用(10)
    set mapred.job.reuse.jvm.num.tasks=10;
    Map: 3255 Reduce: 950 Cumulative CPU: 259683.41 sec HDFS Read: 587550076795 HDFS Write: 725372805057 SUCCESS 28.9MIN
    CPU開銷增加,總執行時間沒有變化

  • 減少map數並設定JVM重用(10)
    Map: 1684 Reduce: 950 Cumulative CPU: 223036.3 sec HDFS Read: 585692215905 HDFS Write: 725372805057 SUCCESS 29.4MIN 效果不大

  • 減少map數並開啟壓縮
    Map: 1684 Reduce: 950 Cumulative CPU: 251331.5 sec HDFS Read: 585697165921 HDFS Write: 136021488023 SUCCESS 26.1MIN
    開啟中間壓縮,對於輸入資料量有少許減少,但是cpu開銷增大,對於單stage任務總體不理想

  • 減少map數並開啟最終壓縮
    Map: 1687 Reduce: 951 Cumulative CPU: 234941.99 sec HDFS Read: 586512467704 HDFS Write: 136164828062 SUCCESS 24.8MIN
    只開啟結果壓縮,cpu資源消耗較之前有所減少,寫入資料量明顯降低,效能有提升

總體來看,效果都不明顯;hive預設使用reduce side join,當兩個表中有一個較小的時候可以考慮map join ,但這兩個表都是大表,可以嘗試使用bucket map join;基本處理方法是將兩個表在join key上做hash bucket,將較小表(sale_history)的bucket設定為較大表(call_result)的數倍。這樣資料就會按照join key做hash bucket。這樣做的話,小表依然會複製到各個節點上,map join的時候,小表的每一組bucket載入成hashtable,與對應的大表bucket做區域性join。
如果兩表的join key 都具有唯一性(是主鍵關聯),還可以進一步做sort merge bucket map join ;做法是兩表都做bucket的基礎上,每個bucket內部還要進行排序,這樣做得好處就是在兩邊的bucket要做區域性join的時候,用類似merge sort演算法中的merge操作一樣把兩個bucket順序遍歷一下即可。
然而以上兩種方法經過測試依然沒有太好的效能表現;穩定在20min之內已經不錯了,又要考慮從源庫抽取資料如何保留等問題,最終無法採用,後經過和業務系統溝通,兩表每天資料量巨大,業務系統不會更新歷史資料,每個表當天的資料是一一對應的,即當天的呼叫和銷售歷史是對應的,因此將程式優化為當天增量資料關聯,資料下降幾個數量級,自然不存在效能問題;
所以,優化無止境,不一定非技術手段不可,首先基於業務邏輯做優化,要做到業務與技術相結合。