impala的sql執行優化過程


文章分兩部分

1 基於impala的sql執行優化過程

2 Impala+kudu架構的數據倉庫經驗分享

第一部分,sql調優

1.老生常談,sql調優必看執行計划,無論是hive還是impala。查看impala的執行計划可以說比較詳細,分為三個粒度,分別是:explain、summary、profile。
(1) impala-shell中執行explain sql,會打印sql語句的執行計划,每一步的解釋如下圖所示:
在這里插入圖片描述

優點:查看執行計划,調整sql語句
缺點:不清楚sql的執行詳情,調整sql語句只能憑經驗

(2) 在sql執行完成后,執行summary可以 看到這條sql語句執行時所消耗的時間和資源的情況,還有Impala預估的資源使用
執行summary語句后打印情況如下圖:
在這里插入圖片描述

優點:明確sql每個階段的執行時間以及資源占用情況,和具體的關聯方式
缺點:執行復雜的sql可能會耗費長時間,只能在sql執行后查看明細

(3)sql執行完成后,執行profile,產生一個詳細的報告顯示低水平的最新查詢被執行。此信息僅在查詢完成后才可用。它顯示物理細節,如讀取字節數、最大內存使用量等每個節點的物理細節,部分顯示如下圖:
在這里插入圖片描述

優點:使用此信息來確定如果查詢是I/O密集型或CPU綁定的,是否有網絡條件實施的瓶頸,是否放緩是影響而不是其他的一些節點,並檢查推薦配置設置,如短路本地讀取效果
缺點:打印輸出的明細數據量非常大,不太容易查看

根據以上三類語句,基本上可以分析清楚sql的執行情況,以及每個階段所消耗的執行時間和資源情況,就可以找出拖累整體運行效率的執行片段,定位到具體環節,針對此過程進行優化就會大大的提高整體sql腳本的執行效率。

優化的側重點主要有一下幾個方面:

  1. 結合執行計划,進行Join 時防止大表被廣播。
  2. 根據實際情況調整關聯方式: broadcast 、(Shuffle)partitioned join
    broadcast 適合大表關聯小表,將小表廣播復制到各個節點,再和左表進行JOIN
    (Shuffle)partitioned join 適合大表和大表關聯. 注意 partitioned join 和右表的 partition 沒有直接關系, impala 會將右表打散成N份, 發送到左表所在的節點, 然后作join
  3. 要寫入大量數據時,盡量使用Kudu的API直接寫入,采用impala寫入時,impala會進行預分區/排序來降低Kudu的負載,並防止大批量的insert超時,but,正是由於這種機制存在,會降低寫入數據時 end-to-end 的性能(impala預處理,在執行很長時間后才能查到數據,不讓impala預處理,目標表很快就能查到數據),從CDH5.13/Impala2.10起,可以使用/* +NOCLUSTERED*/、/NOSHUFFLE /讓impala不預排序、分區數據。
    例如 insert into table_a /
     +NOCLUSTERED
    /,/*NOSHUFFLE */ select * from table_b

參照網址:https://docs.cloudera.com/documentation/enterprise/5-16-x/topics/impala_kudu.html#kudu_dml

  1. 定期對表收集統計信息, 或者在大量DML操作后主動收集統計信息. 執行 COMPUTE STATS table,需要注意的是此語句在進行大表操作時會耗費相當長的時間
  2. 使用not in,not exists 默認將右表廣播,而且沒法指定partitioned join ,使用left anti join
  3. 使用 straight_join 進行自定義表的關聯順序,不按照impala優化器的優化順序執行
  4. 根據 summary 的結果,確定出需要優化的位值,減少關聯數據量和表字段
    (各位大佬有其他途徑或者方法,希望留言告知,非常感謝)

第二部分,Impala+kudu架構的數據倉庫經驗分享

impala + kudu 在數據倉庫中需要注意的點:(淺談經驗)

  1. kudu表的類型及其優缺點 range分區 如果創建時間序列的分區,分區忘記創建容易導致數據寫入失敗 Hash分區會導致數據表越來越大,查詢檢索性能收到影響
  2. kudu 進行大批量的delete效率低,並且集群產生垃圾較多(必要時候直接drop,再create,效率會更高,空間也會釋放)
  3. 在進行數據倉庫分層統計時,應保持相應的數據一致性,這個是kudu目前發現的比較雞肋的點,就是沒有overwrite 功能,不能重寫,不能truncate table/partitions。
 在數據處理過程中,會出現如下情況: 第一次寫入數據為10由於當第一次計算錯誤。 第二次計算將新結果寫入時,用upsert只會更新和添加與第一次主鍵重復或者新增的數據,比如更新了8條,那么表里會有兩條臟數據,沒法處理。 這種情況有兩種方式處理: 第一,當數據為中間結果表,量級小時可以采取的措施要么進行drop或者delete,清空或者重建表重新插入。 第二,在新數據插入/更新之前,將表中的數據進行標記刪除,之后插入的數據會更新標記,此操作相對合理 (另一種方式可以借助 Parquet 列式存儲格式的hive表,Impala+Parquet 查詢性能也是非常快,並且可以使用overwrite,避免產生數據垃圾) 
    1. 在執行ETL操作前,盡可能執行compute stats 表名,不然impala執行sql生成的計划執行數評估的內存不准確,容易評估錯誤導致實際執行不了

    2. 查看kudu表分區下所占的存儲空間 和表總的存儲空間
      a.查看表整體所占用的存儲空間,如下圖:
      在這里插入圖片描述

      b.查看表分區所占的存儲空間
      Cloudera Manager -->進入Kudu --> 進入Web UI–如下圖:
      在這里插入圖片描述
      進入Tablet Servers之后就能查看集群節點的Tablet Servers詳情列表,如下圖
      在這里插入圖片描述
      進入任意一個Tablet Servers后,能夠查到具體的表對應的分區大小,如下圖:
      在這里插入圖片描述


免責聲明!

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



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