目次
4.3.1 パーティションテーブルのデータロード -- 動的パーティション
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.* を選択するなど)。このようなクエリでは、バケット テーブルを使用しない場合、基になるデータは次の数に基づく必要があります。デカルト積 スキャンしてクエリを実行し、バケット テーブルの場合、その後のフィールドがバケット フィールドだった場合、クエリ データは特定のバケットで実行され、データ量が削減されるため、デカルト積の数はも大幅に削減されます。
バケット化されたテーブルを使用したデータの効率的なサンプリング
データ量が特に多く、すべてのデータを処理することが難しい場合、サンプリングは特に重要になります。サンプリングは、サンプリングしたデータから全体の特徴を推定・推測することができ、科学実験や品質検査、社会調査などでよく使われる経済的で効果的な作業・研究手法です。