【Hiveビッグデータ】Hiveパーティションテーブルとバケットテーブルの使い方を詳しく解説

目次

1. パーティション構想の背景

次に、パーティションテーブルの特徴

3. パーティションテーブルの種類

3.1 単一パーティション

3.2 マルチパーティション

4、動的パーティションと静的パーティション

4.1 静的パーティション [静的読み込み]

4.1.1 動作デモ

4.2 複数のパーティション

4.2.1 動作デモ

4.3 パーティションデータの動的ロード

4.3.1 パーティションテーブルのデータロード -- 動的パーティション

4.3.2 動作デモ

5.バケットテーブル

5.1 バケットテーブルの概念

5.2 バケット化ルールの説明

5.2.1 バケット化の基本ルール

5.3 バケットの完全な構文ツリー

5.4 バケットテーブルの動作デモ

5.4.1 テーブルの作成

5.4.2 バケットテーブルを使用する利点


1. パーティション構想の背景

Hive を使用してテーブルをクエリする場合 (例: select * from t_user where name ='lihua')、Hive がこの SQL を実行すると、通常、テーブル全体のデータがスキャンされます。完全なテーブル スキャンの効率は非常に低いことがわかっています。特に、hive の最終データ クエリのために hdfs ファイルをスキャンするのはさらに効率が悪くなります。

実際、ビジネスにおいてクエリが必要なデータはフルテーブルスキャンを必要としないケースが多いですが、クエリされたデータは特定の領域にあることが予測できます。この前提に基づいて、Hive ではパーティション (パーティション) が導入されています。 )の概念。テーブルの作成に対応する構文ツリーの場所は次のとおりです。

次に、パーティションテーブルの特徴

パーティション テーブルは、テーブルの作成時に指定されたパーティションのパーティション スペースを指します。パーティション テーブルを作成する必要がある場合は、テーブルの作成時にオプションのパラメータ Partitioned by を呼び出す必要があります。

  • テーブルには 1 つ以上のパーティションを含めることができ、各パーティションはテーブル フォルダーのディレクトリの下にフォルダーの形式で存在します。

  • テーブル名と列名は大文字と小文字が区別されません。

  • パーティションはフィールドの形式でテーブル構造に存在します。desc 形式の table コマンドを使用してフィールドの存在を表示できますが、このフィールドには実際のデータ内容は格納されず、パーティションを表すだけです。

3. パーティションテーブルの種類

パーティション テーブルは、テーブル作成時のパーティション フィールドの数に応じて、次のように単一パーティション テーブルとマルチパーティション テーブルに分けられます。

3.1 単一パーティション

単一パーティションとは、テーブル フォルダー ディレクトリの下に、第 1 レベルのフォルダー ディレクトリが 1 つだけ存在することを意味します。テーブルを作成するとき、PARTITIONED BY のフィールドは 1 つだけです。次のように、州ごとに単一のパーティションになります。


(都道府県文字列) で分割されたテーブル t_user_province ( 
    id int, 
    name string, 
    age int ) を作成します。

3.2 マルチパーティション

もう 1 つは、マルチ パーティションであり、テーブル フォルダの下にマルチ フォルダのネスト モードが表示されます。テーブルを作成するときに、ビジネス ニーズに応じて複数のパーティション フィールドを指定できます。以下は、州、都市ごとにパーティション化された 3 つのパーティション テーブルです。 、および郡。


(県文字列、都市文字列、郡文字列) で分割されたテーブル t_user_province_city_county ( 
    id int, 
    name string, 
    age int ) を作成します。

4、動的パーティションと静的パーティション

4.1 静的パーティション [静的読み込み]

静的パーティションは、データをロードするときにユーザーが手動で指定するパーティションの属性値を指します。構文は次のとおりです。

パス「ファイルパス」のデータ[ローカル]をテーブルテーブル名にロードします。 パーティション(パーティションフィールド=「パーティション値」...);

知らせ:

Local パラメーターは、ロードするデータがローカル ファイル システムにあるのか HDFS ファイル システムにあるのかを指定するために使用されます。

4.1.1 動作デモ

パーティションテーブルを作成する

パーティション フィールドとしてロールを持つパーティション テーブル t_all_hero_part を作成します。

create table t_all_hero_part( 
   id int, 
   name string, 
   hp_max int, 
   mp_max int, 
   Attack_max int, 
   Defense_max int, 
   Attack_range string, 
   role_main string, 
   role_assist string 
) (ロール文字列) でパーティション
化された行フォーマット区切り
フィールドは「\t」で終了します。

上記の SQL を実行してパーティション テーブルを作成します。

このテーブルには、役割の追加のパーティション フィールドがあることがわかります。

ローカル データをサーバー ディレクトリにアップロードする

次のローカル テスト データ ファイルを指定されたディレクトリにアップロードします

データをハイブにロードする

次のコマンドを使用して、ローカル データ ファイルをハイブ テーブルにロードします。

ローカルのパス '/usr/local/soft/hivedata/archer.txt' をテーブル t_all_hero_part パーティションにロードします (role='sheshou'); 
ローカルのパス「/usr/local/soft/hivedata/assassin.txt」のデータをテーブル t_all_hero_part パーティションにロードします(role='cike'); 
ローカルのパス「/usr/local/soft/hivedata/mage.txt」のデータをテーブル t_all_hero_partpartition(role='fashi') にロードします。
ローカルのパス '/usr/local/soft/hivedata/support.txt' をテーブル t_all_hero_part パーティションにロードします (role='fuzhu'); 
ローカルのパス「/usr/local/soft/hivedata/tank.txt」のデータをテーブル t_all_hero_partpartition(role='tanke') にロードします。
ローカルのパス '/usr/local/soft/hivedata/warrior.txt' をテーブル t_all_hero_part パーティションにロードします (role='zhanshi');

実装プロセス

データを確認すると、データがパーティション テーブルに正常にマップされていることがわかります。最後の列がパーティション フィールドであることに注意してください。

同時に、HDFS ディレクトリ内のデータは次の構造を示します。

静的パーティション テーブルのデータ ストレージは非常に規則的で、外側の層はパーティション名をディレクトリとして使用し、内側の層は現在のパーティションの特定のデータ ファイルになります。

このテーブルと通常の非パーティション テーブルの違いは一目瞭然なので詳細は説明しませんが、この直感的な方法を通じて、パーティション テーブルの概念を次のようにさらに理解することができます。

  • パーティショニングの概念は、Hive テーブル データを複数のファイル/ディレクトリに分割する方法を提供します。

  • 異なるパーティションは異なるフォルダーに対応し、同じパーティションのデータは同じフォルダーに保存されます。

  • クエリとフィルタリングを行う場合、テーブル全体のデータ スキャンを避けるために、パーティション値に従って対応するフォルダーを検索し、このフォルダーの下にあるこのパーティションにあるファイルをスキャンするだけで済みます。

  • パーティション クエリを指定するこの方法は、パーティション プルーニングと呼ばれます。

このとき、次の SQL を使用してクエリを実行すると、最初にパーティションを見つけて、そのパーティション内のデータ ファイルのみをクエリできるため、テーブル全体をスキャンする必要がなくなり、効率が大幅に向上します。 ;

select * from t_all_hero_part where role="sheshou" および hp_max >6000;

4.2 複数のパーティション

テーブル作成ステートメントのパーティションに関する関連構文から、Hive が複数のパーティション フィールドをサポートしていることがわかります。

PARTITIONED BY (パーティション 1 のデータ型、パーティション 2 のデータ型、…)

複数のパーティションの下では、パーティション間には漸進的な関係があり、前のパーティションに基づいてパーティションを分割し続けると理解できますが、HDFS の観点からは、フォルダーの下のサブフォルダーを分割し続けることを意味します。たとえば、まず全国人口データを州に従って分割し、次に都市に従って分割します。必要に応じて、引き続き地区および郡に従って分割することもできます。現時点では、それは 3-パーティションテーブル。

4.2.1 動作デモ

2 つのパーティション テーブルを作成する

都道府県と市区町村ごとに分割したデュアルパーティションテーブルを作成する

(県文字列, 都市文字列) で分割されたテーブル t_user_province_city (id int, name string,age int) を作成します。

州、市、郡ごとに分割された 3 つのパーティション テーブルを作成する

(県文字列、都市文字列、郡文字列) で分割されたテーブル t_user_province_city_county (id int, name string,age int) を作成します。

4.3 パーティションデータの動的ロード

上記のloadメソッドを使用してパーティションデータを手動で指定する方法は、静的パーティション(静的ローディング)とも呼ばれますが、実際に使用する場合、多数のパーティションを作成するとloadコマンドで何度もロードすることになりますので、効率は非常に低いはずですが、現時点では、Hive の動的パーティションの使用を検討できます。

4.3.1 パーティションテーブルのデータロード -- 動的パーティション

  • いわゆる動的パーティションとは、パーティションのフィールド値がクエリ結果 (パラメータの位置) に基づいて自動的に推測されることを意味します。中心的な構文は挿入+選択です。

ハイブの動的パーティショニングを有効にするには、ハイブ セッションで 2 つのパラメータを設定する必要があります。

#動的パーティション機能を有効にするかどうか
set hive.exec.dynamic.partition=true; 
#ノンスティック非厳密モードと厳密厳密モードに分かれる動的パーティション モードを
指定します
#厳密厳密モードでは、少なくとも 1 つのパーティションが必要です静的パーティション
set hive.exec .dynamic.partition.mode=nonstrict であること

4.3.2 動作デモ

新しいパーティション テーブルを作成し、動的パーティション挿入を実行します。SQL テーブル作成ステートメントは次のとおりです。

create table t_all_hero_part_dynamic( 
    id int, 
    name string, 
    hp_max int, 
    mp_max int, 
    Attack_max int, 
    Defense_max int, 
    Attack_range string, 
    role_main string, 
    role_assist string 
) (ロール文字列) でパーティション化さ
れた行フォーマット区切り
フィールドは「\t」で終了します。

上記の SQL を実行する前に、現在のセッションで次のパラメータを設定する必要があります。

hive.exec.dynamic.partition=true を設定します。
hive.exec.dynamic.partition.mode=nonstrict を設定します。

作成が完了したら、以下のSQLを実行して前のテーブルのデータをインポートします。

テーブル t_all_hero_part_dynamic パーティション (ロール) に挿入します。 t_all_hero tmp から tmp.*,tmp.role_main を選択します。

実行に時間がかかる場合がある

 

hdfs 上の動的テーブルのディレクトリを表示すると、データ ファイルも予想されるパーティション フィールドに従って分割されていることがわかります。

パーティションテーブルに関する注意:

  • パーティション テーブルは、テーブルを作成するために必要な文法規則ではありません。テーブルの最適化手段であり、オプションです。

  • パーティション フィールドをテーブル内の既存のフィールドにすることはできず、繰り返すこともできません。

  • パーティション フィールドは仮想フィールドであり、そのデータは基礎となるファイルには格納されません。

  • パーティション フィールド値の決定は、ユーザー値データの手動指定 (静的パーティション) またはクエリ結果の場所に基づく自動推論 (動的パーティション) によって行われます。

  • Hive は複数のパーティションをサポートします。つまり、パーティションはパーティションに基づいて継続され、パーティションはよりきめ細かくなります。

5.バケットテーブル

5.1 バケットテーブルの概念

バケット テーブルは、バケット テーブルとも呼ばれます。名前は、テーブル作成構文のバケットという単語に由来しています。クエリを最適化するために設計されたテーブル タイプです。バケット テーブルに対応するデータ ファイルは、下部でいくつかの部分に分解されます。バケットを分割する場合、データをどのフィールドに応じて複数のバケット (いくつかの部分) に分割するかを指定する必要があります。

5.2 バケット化ルールの説明

5.2.1 バケット化の基本ルール

同じバケット番号を持つデータは同じバケットに割り当てられます。

バケット番号 = hash_function(bucketing_column) mod num_buckets
      バケット番号 = ハッシュ方式 (バケットフィールド) モジュロバケット番号

hash_function は、bucketing_column のタイプによって異なります。

  • int型の場合、 hash_function(int) == int;

  • bigint、string、または複雑なデータ型などの他のデータ型の場合、hash_function はさらに複雑で、ハッシュコード値など、この型から派生した数値になります。

5.3 バケットの完全な構文ツリー

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name 
[(col_name データ型 [COMMENT 列コメント], ... ] 
[COMMENT テーブルコメント] 
[PARTITIONED BY (列名 データ型 [COMMENT 列コメント], ...) ] 
[CLUSTERED BY (col_name,col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] [ROW FORMAT DELIMITED 
|SERDE serde_name WITH SERDEPROPERTIES (property_name=property_value,...) )] 
[STORED AS file_format] 
[LOCATION hdfs_path] 
[TBLPROPERTIES (property_name=property_value, ...)];

バケットキーパラメータの説明:

  • CLUSTERED BY (col_name) は、分割に使用されるフィールドを示します。

  • INTO N BUCKETS は、複数のバケット (つまり、いくつかの部分) に分割されることを意味します。

  • バケット化のフィールドは、テーブルにすでに存在するフィールドである必要があることに注意してください。

最も単純なバケット SQL

CREATE [EXTERNAL] TABLE [db_name.]table_name 
[(col_name data_type, ...)] 
CLUSTERED BY (col_name) 
INTO N BUCKETS;

5.4 バケットテーブルの動作デモ

要件としては、以下のデータファイルがあります。

ファイルの内容の解釈:

  • このコンテンツには、米国の各郡における 2021 年 1 月 28 日の新型コロナウイルス感染症の累積感染者数 (確定症例と死亡者数を含む) が示されています。

  • フィールドの意味: count_date (統計日付)、county (郡)、state (州)、fips (郡コード コード)、cases (累積確認症例)、death (累積死亡症例)。

5.4.1 テーブルの作成

バケット化フィールドはテーブルにすでに存在するフィールドである必要があります

フィールドソートのないバケットテーブル

状態フィールドに従って、データは 5 つのバケットに分割され、テーブル作成ステートメントは次のようになります。

CREATE TABLE t_usa_covid19_bucket( 
      count_date string, 
      county string, 
      state string, 
      fips int, 
      case int, 
      deaths int) 
CLUSTERED BY(state) INTO 5 BUCKETS;

フィールドソートを備えたバケットテーブル

状態フィールドに従って、5つのバケットに分割され、各バケットは確認された症例数に応じて逆順に並べ替えられます。

CREATE TABLE t_usa_covid19_bucket_sort( 
     count_date string, 
     county string, 
     state string, 
     fips int, 
     case int, 
     deaths int) 
CLUSTERED BY(state) 
sort by (cases desc) INTO 5 BUCKETS;

作成が成功したら、hdfs を確認すると、テーブルの関連データ ディレクトリが表示されます。

注: ハイブのバケット テーブルにデータをインポートする場合、hdfs コマンドを直接使用してデータ ファイルをテーブル ディレクトリに直接ロードすることはできなくなり、insert + select を使用する必要があります。

上記で作成したバケットテーブルにデータをインポートするには、まず通常のテーブルを作成し、次のようにテーブルSQLを作成します。

CREATE TABLE t_usa_covid19( 
       count_date string, 
       county string, 
       state string, 
       fips int, 
       case int, 
       deaths int) 
「,」で終わる行形式の区切りフィールド。

データ ファイルをテーブルにアップロードします。

hdfs dfs -put ./us-covid19-counties.dat /user/hive/warehouse/test.db/t_usa_covid19

実行が成功した後、テーブルのデータを確認すると、データが正常にロードされたことがわかります。

挿入 + 選択構文を使用してデータをバケット テーブルにロードします

t_usa_covid19_bucket に挿入 * から t_usa_covid19 を選択します。

Map-Reduce タスクが完了したことを確認した後、バケット テーブルのデータを確認します。この時点でデータがロードされます。

HDFS 上の t_usa_covid19_bucket の基礎となるデータ構造を見ると、データが 5 つの部分に分割されていることがわかります。その結果から、同じバケット フィールドを持つデータは同じバケットに分割する必要があることがわかります。

次に、テストを行います。バケット フィールドの状態に基づいてニューヨーク州のデータをクエリします。データは州 (州) に従ってバケット化されるため、クエリの際にテーブル全体をスキャンしてフィルターする必要はなくなります。最下層では、クエリを実行すると、バケット番号がバケット ルール hash_function(New York) mod 5 に従って計算され、指定されたバケット内のデータをクエリして、結果が完全なスキャンではなくバケット スキャンであることを確認できます。テーブルスキャン。

select * from t_usa_covid19_bucket where state="ニューヨーク";

クエリ速度の点では、依然として非常に高速です。

5.4.2 バケットテーブルを使用する利点

バケット化されたフィールドに基づいてクエリを実行する場合のフルテーブルスキャンを削減します。

バケット化後、バケット化フィールドに従ってフィルタリングすると、データ量が大幅に削減され、テーブル全体のスキャンが回避され、クエリ効率が向上します。

JOIN は MR プログラムの効率を向上させ、デカルト積の数を減らすことができます

通常の 2 つのテーブルに関連付けられたクエリ (a.id = b.id の結合 b から a.* を選択するなど)。このようなクエリでは、バケット テーブルを使用しない場合、基になるデータは次の数に基づく必要があります。デカルト積 スキャンしてクエリを実行し、バケット テーブルの場合、その後のフィールドがバケット フィールドだった場合、クエリ データは特定のバケットで実行され、データ量が削減されるため、デカルト積の数はも大幅に削減されます。

バケット化されたテーブルを使用したデータの効率的なサンプリング

データ量が特に多く、すべてのデータを処理することが難しい場合、サンプリングは特に重要になります。サンプリングは、サンプリングしたデータから全体の特徴を推定・推測することができ、科学実験や品質検査、社会調査などでよく使われる経済的で効果的な作業・研究手法です。

おすすめ

転載: blog.csdn.net/congge_study/article/details/128888831