將 Azure HDInsight 中的 Apache Hive 查詢最佳化

本文說明一些最常見的效能優化,可用來改善Apache Hive查詢的效能。

叢集類型選取

在 Azure HDInsight 中,您可以在幾個不同的叢集類型上執行 Apache Hive 查詢。

選擇適當的叢集類型,以協助優化工作負載需求的效能:

  • 選擇 [互動式查詢 ] 叢集類型,以針對 ad hoc互動式查詢進行優化。
  • 選擇 Apache Hadoop 叢集類型,以針對作為批處理使用的 Hive 查詢進行優化。
  • SparkHBase 叢集類型也可以執行 Hive 查詢,而且如果您執行這些工作負載,可能適用。

如需在各種 HDInsight 叢集類型上執行 Hive 查詢的詳細資訊,請參閱 什麼是 Azure HDInsight 上的 Apache Hive 和 HiveQL?

向外延展背景工作節點

增加 HDInsight 叢集中的背景工作節點數目,可讓工作使用更多對應器和歸納器平行執行。 在 HDInsight 中,有兩種方式可以增加相應放大:

  • 當您建立叢集時,您可以使用 Azure 入口網站、Azure PowerShell 或命令行介面來指定背景工作節點的數目。 如需詳細資訊,請參閱 建立 HDInsight 叢集。 下列螢幕快照顯示 Azure 入口網站 上的背景工作節點設定:

    Azure portal cluster size nodes.

  • 建立之後,您也可以編輯背景工作節點數目,以進一步相應放大叢集,而不需要重新建立一個:

    Azure portal scale cluster size.

如需調整 HDInsight 的詳細資訊,請參閱 調整 HDInsight 叢集

使用 Apache Tez 而非 Map Reduce

Apache Tez 是 MapReduce 引擎的替代執行引擎。 以 Linux 為基礎的 HDInsight 叢集預設啟用 Tez。

HDInsight Apache Tez overview diagram.

Tez 的速度較快,因為:

  • 在 MapReduce 引擎中,以單一作業的形式執行有向非循環圖 (DAG)。 DAG 要求每組對應器後面接著一組 Reducer。 這項需求會導致每個 Hive 查詢有多個 MapReduce 作業遭到關閉。 Tez 沒有這類條件約束,而且可以將複雜的 DAG 處理為一項作業,以將作業啟動額外負荷降至最低。
  • 避免不必要的寫入。 多項作業可用來處理 MapReduce 引擎中的相同 Hive 查詢。 每個 MapReduce 作業的輸出都會寫入 HDFS 以取得中繼資料。 由於 Tez 將每個 Hive 查詢的作業數目降到最低,因此可以避免不必要的寫入。
  • 將啟動延遲降至最低。 Tez 藉由減少需要啟動的對應器數目,以及改善整個最佳化,以將啟動延遲降到最低。
  • 重複使用容器。 只要有可能,Tez 就會重複使用容器,以確保減少啟動容器的延遲。
  • 持續最佳化技術。 傳統上會在編譯階段完成最佳化。 不過,我們提供了有關輸入的詳細資訊,可在執行階段進行更好的最佳化。 Tez 會使用持續最佳化技術,讓其進一步將方案最佳化至執行階段。

如需這些概念的詳細資訊,請參閱 Apache TEZ

您可以使用下列 set 命令在查詢前面加上前置詞,以啟用任何 Hive 查詢 Tez:

set hive.execution.engine=tez;

Hive 數據分割

I/O 作業是執行Hive查詢的主要效能瓶頸。 如果可以減少需要讀取的數據量,則可以改善效能。 根據預設,Hive 查詢會掃描整個Hive數據表。 不過,對於只需要掃描少量數據的查詢(例如,具有篩選的查詢),此行為會產生不必要的額外負荷。 Hive 分割可讓Hive查詢只存取Hive資料表中所需的數據量。

Hive 資料分割是藉由將原始數據重新組織成新的目錄來實作。 每個分割區都有自己的檔案目錄。 使用者定義數據分割。 下圖說明依 [Year] 數據行分割 Hive 數據表。 每年都會建立新的目錄。

HDInsight Apache Hive partitioning.

一些數據分割考慮:

  • 請勿在數據分割 之下 - 在只有少數值的數據行上進行數據分割可能會導致少數數據分割。 例如,在性別上進行分割只會建立兩個分割區(男性和女性),因此將延遲減少最多一半。
  • 不要超過數據分割 - 在其他極端情況下,在具有唯一值的數據行上建立數據分割(例如 userid)會導致多個分割區。 在數據分割上,叢集 namenode 會造成很大的壓力,因為它必須處理大量的目錄。
  • 避免數據扭曲 - 明智地選擇數據分割索引鍵,讓所有分割區都是偶數大小。 例如,在 [狀態] 數據行上進行數據分割可能會扭曲數據的分佈。 由於加州有近 30 倍的佛蒙特州人口,因此分割區大小可能會扭曲,而且效能可能會有很大的差異。

若要建立數據分割數據表,請使用 Partitioned By 子句:

CREATE TABLE lineitem_part
      (L_ORDERKEY INT, L_PARTKEY INT, L_SUPPKEY INT,L_LINENUMBER INT,
      L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE,
      L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING,
      L_SHIPDATE_PS STRING, L_COMMITDATE STRING, L_RECEIPTDATE STRING,
      L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT STRING)
PARTITIONED BY(L_SHIPDATE STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;

建立資料分割數據表之後,您可以建立靜態數據分割或動態數據分割。

  • 靜態數據分割 表示您已經在適當的目錄中分區化數據。 使用靜態分割區時,您會根據目錄位置手動新增Hive分割區。 下列代碼段是範例。

    INSERT OVERWRITE TABLE lineitem_part
    PARTITION (L_SHIPDATE = '5/23/1996 12:00:00 AM')
    SELECT * FROM lineitem
    WHERE lineitem.L_SHIPDATE = '5/23/1996 12:00:00 AM'
    
    ALTER TABLE lineitem_part ADD PARTITION (L_SHIPDATE = '5/23/1996 12:00:00 AM')
    LOCATION 'wasb://sampledata@ignitedemo.blob.core.windows.net/partitions/5_23_1996/'
    
  • 動態數據分割 表示您希望Hive自動為您建立資料分割。 由於您已經從臨時表建立資料分割數據表,您只需要將數據插入數據分割數據表:

    SET hive.exec.dynamic.partition = true;
    SET hive.exec.dynamic.partition.mode = nonstrict;
    INSERT INTO TABLE lineitem_part
    PARTITION (L_SHIPDATE)
    SELECT L_ORDERKEY as L_ORDERKEY, L_PARTKEY as L_PARTKEY,
         L_SUPPKEY as L_SUPPKEY, L_LINENUMBER as L_LINENUMBER,
         L_QUANTITY as L_QUANTITY, L_EXTENDEDPRICE as L_EXTENDEDPRICE,
         L_DISCOUNT as L_DISCOUNT, L_TAX as L_TAX, L_RETURNFLAG as L_RETURNFLAG,
         L_LINESTATUS as L_LINESTATUS, L_SHIPDATE as L_SHIPDATE_PS,
         L_COMMITDATE as L_COMMITDATE, L_RECEIPTDATE as L_RECEIPTDATE,
         L_SHIPINSTRUCT as L_SHIPINSTRUCT, L_SHIPMODE as L_SHIPMODE,
         L_COMMENT as L_COMMENT, L_SHIPDATE as L_SHIPDATE FROM lineitem;
    

如需詳細資訊,請參閱 分割數據表

使用 ORCFile 格式

Hive 支援不同的檔案格式。 例如:

  • 文字:預設檔格式,適用於大部分案例。
  • Avro:適用於互操作性案例。
  • ORC/Parquet:最適合效能。

ORC (Optimized Row Columnar) 格式是儲存 Hive 資料的高效方式。 與其他格式相比,ORC 具有下列優點:

  • 支援複雜類型,包括 DateTime 和複雜和半結構化類型。
  • 最多 70% 的壓縮。
  • 索引每 10,000 個數據列,允許略過數據列。
  • 運行時間執行大幅下降。

若要啟用 ORC 格式,您必須先建立包含儲存為 ORC 子句的數據表:

CREATE TABLE lineitem_orc_part
      (L_ORDERKEY INT, L_PARTKEY INT,L_SUPPKEY INT, L_LINENUMBER INT,
      L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE,
      L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING,
      L_SHIPDATE_PS STRING, L_COMMITDATE STRING, L_RECEIPTDATE STRING,
      L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT      STRING)
PARTITIONED BY(L_SHIPDATE STRING)
STORED AS ORC;

接下來,您會將數據從臨時表插入 ORC 資料表。 例如:

INSERT INTO TABLE lineitem_orc
SELECT L_ORDERKEY as L_ORDERKEY,
         L_PARTKEY as L_PARTKEY ,
         L_SUPPKEY as L_SUPPKEY,
         L_LINENUMBER as L_LINENUMBER,
         L_QUANTITY as L_QUANTITY,
         L_EXTENDEDPRICE as L_EXTENDEDPRICE,
         L_DISCOUNT as L_DISCOUNT,
         L_TAX as L_TAX,
         L_RETURNFLAG as L_RETURNFLAG,
         L_LINESTATUS as L_LINESTATUS,
         L_SHIPDATE as L_SHIPDATE,
         L_COMMITDATE as L_COMMITDATE,
         L_RECEIPTDATE as L_RECEIPTDATE,
         L_SHIPINSTRUCT as L_SHIPINSTRUCT,
         L_SHIPMODE as L_SHIPMODE,
         L_COMMENT as L_COMMENT
FROM lineitem;

您可以在 Apache Hive 語言手冊深入瞭解 ORC 格式。

向量化

向量化可讓 Hive 一起處理 1024 個資料列的批次,而不是一次處理一個資料列。 這表示簡單的作業會更快完成,因為需要執行較少的內部程式碼。

若要使用下列設定來啟用Hive查詢的向量化前置詞:

set hive.vectorized.execution.enabled = true;

如需詳細資訊,請參閱 向量化查詢執行

其他最佳化方法

您可以考慮更多優化方法,例如:

  • Hive 貯體: 一種技術,可讓叢集或分割大型數據集,以優化查詢效能。
  • 聯結優化: 優化Hive的查詢執行規劃,以改善聯結的效率,並減少使用者提示的需求。 如需詳細資訊,請參閱 聯結優化
  • 增加歸納器

下一步

在本文中,您已了解數個常見的Hive查詢優化方法。 如需詳細資訊,請參閱下列文章: