「オフラインおよびリアルタイムのビッグデータ開発の戦い」(4)ハイブの原則の実践

序文

Hive SQLが実際に実行のためにMapReduceに変換されることは誰もが知っていますが、具体的なプロセスは何ですか?今日は、HiveSQLの背後にある実行メカニズムと原則について説明します。

Hive SQLの実行原理をさらに理解して習得することは、通常のオフラインタスクの開発と最適化にとって非常に重要であり、HiveSQLの実行効率と時間に直接関係します。

1.ハイブの基本アーキテクチャ

Hadoopに基づく主要なデータウェアハウスソリューションとして、Hive SQLは主要なインタラクティブインターフェイスです。実際のデータはHDFSファイルに保存されます。実際の計算と実行はMapReduceによって行われます。それらの間のブリッジは、Hiveエンジンです。

ハイブエンジンアーキテクチャ
Hiveの主なコンポーネントには、UIコンポーネント、ドライバーコンポーネント(Complier Optimizer Executor)、メタストアコンポーネント、CLI(コマンドラインインターフェイス)、JDBC / ODBC、Thrift Server、Hive Webインターフェイス(HWI)などがあります。

Hiveは、CLI、JDBC / ODBC、またはHWIを介して関連するHive SQLクエリを受信し、Driverコンポーネントを介してそれらをコンパイル、分析、および最適化し、最終的に実行可能なMapReduceに変換します。

Hiveの主要コンポーネントの実行プロセス

二、Hive SQL

HiveSQLはANSISQL標準に似たSQL言語ですが、2つは完全に同じではありません。Hive SQLとMySQLのSQL言語が最も近いですが、両者の間にも大きな違いがあります。たとえば、Hiveは行レベルのデータの挿入、更新、削除をサポートしておらず、トランザクションもサポートしていません。

ハイブの重要な概念

1.ハイブデータベース

Hiveのデータベースは基本的に単なるディレクトリまたは名前付けですが、この概念は多くのユーザーとグループが存在するクラスターに非常に役立ちます。

まず、これによりテーブル名の競合を回避できます。次に、リレーショナルデータベースのデータベースの概念と同等です。これは、テーブルのセットまたはテーブルの論理グループであり、非常に理解しやすいものです。

2. Hive 表

Hiveのテーブルとリレーショナルデータベースのテーブルは概念的に類似しています。各テーブルには、Hiveにデータを格納するための対応するディレクトリがあります。指定されたテーブルのデータベースがない場合、Hiveはの{HIVE_HOME} /conf/hive-site.xml構成ファイルを使用します。hive.metastore.warehouse.dir属性はデフォルト値を使用し(通常/user/hive/warehouse、実際の状況に応じて構成を変更することもできます)、すべてのテーブルデータ(外部テーブルを除く)がこのディレクトリに保存されます。

ハイブテーブルは、内部テーブルと外部テーブルの2つのカテゴリに分類されます。いわゆる内部テーブル(管理対象テーブル)とは、Hiveが管理するテーブルを指します。Hive内部テーブルの管理には、論理的、文法的、および実際の物理的意味の両方が含まれます。つまり、Hive内部テーブルが作成されると、データは実際にはテーブルが配置されているディレクトリに存在します。内部では、内部テーブルが削除されると、物理データとファイルも削除されます。

では、内部テーブルと外部テーブルのどちらを選択するのでしょうか。

ほとんどの場合、2つの違いは明らかではありません。すべてのデータ処理がHiveで実行される場合は、内部テーブルが優先されます。ただし、Hiveと他のツールが同じデータセットを処理する場合は、外部テーブルの方が適しています。

  • 一般的なパターンは、外部テーブルを使用してHDFSに保存されている初期データ(通常は他のツールによって作成されます)にアクセスし、Hiveを使用してデータを変換し、結果を内部テーブルに配置することです。逆に、外部テーブルを使用して、Hiveの処理結果を他のアプリケーションにエクスポートすることもできます。

  • 外部テーブルを使用する別のシナリオは、データセットに複数のスキーマを関連付けることです。

3.パーティションとバケット

Hiveはテーブルをパーティションに分割し、パーティションはパーティションフィールドに従って実行されます。パーティショニングにより、データの部分的なクエリを高速化できます。テーブルまたはパーティションは、さらにバケットに分割できます。バケットは通常、元のデータにいくつかの追加の構造を追加します。これは、効率的なクエリに使用できます。

たとえば、ユーザーIDベースのバケット化により、ユーザーベースのクエリを非常に高速に実行できます。

(1)パーティション

ログデータで、各レコードにタイムスタンプがあると想定します。時間で分割すると、同じ日のデータが同じパーティションに分割されます。

パーティショニングは複数の次元で実行できます。たとえば、日付で割った後、国ごとにさらに分けることができます。

Hiveパーティションに対応する物理構造の例
PARTITIONED BY定義された句のテーブルを作成するときに使用されるパーティション。この句は、フィールドのリストを受け取ります。

CREATE TABLE logs (ts BIGINT , line STRING)
PARTITIONED BY (dt STRING,country STRING);

データをパーティションテーブルにインポートする場合、パーティションの値は明示的に指定されます。

LOAD DATA INPATH ’/user/root/path’ 
INTO TABLE logs 
PARTITION (dt='2001-01-01',country='GB’);

実際のSQLは、パーティションを柔軟に指定すると効率が大幅に向上します。次のコードはディレクトリ2001-01-01のみスキャンさGBます。

SELECT ts , dt , line FROM logs WHERE dt=2001-01-01' and country='GB' 
(2)バケットを分割する

通常、テーブルまたはパーティションでバケットを使用する理由は2つあります。

  • 1つは効率的なクエリです。バケットはテーブルに特別な結果を追加し、Hiveはこれらの構造を使用してクエリの効率を向上させることができます。たとえば、2つのテーブルが同じフィールドに従ってバケット化されている場合、2つのテーブルを関連付けるときに、関連付けられたフィールドがバケットフィールドに表示されていれば、マップ側の関連付けを使用して効率的に実装できます。
  • 第二に、サンプリングを効率的に実行できます。大規模なデータセットを分析する場合、サンプリングされたデータの一部を観察および分析する必要があることがよくあります。バケット化は、効率的なサンプリングに役立ちます。

HiveテーブルをCLUSTERED BY作成するには、句のテーブルを作成するときに指定してバレルを分割します。

CREATE TABLE bucketed users(id INT, name STRING) 
CLUSTERED BY (id) INTO 4 BUCKETS;

指定されたテーブルは、idフィールドに従ってバケット化され、4つのバケットに分割されます。バケットを分割するとき、Hiveはフィールドハッシュ後の残りに応じて、データを配置するバケットを決定します。したがって、各バケットはデータ全体のランダムなサンプルです。

マップ側の関連付けでは、2つのテーブルが同じフィールドに従ってバケット化されるため、左側のテーブルのバケットを処理するときに、関連付け操作のために外側のテーブルに対応するバケットからデータを直接抽出できます。マップ側に関連付けられた2つのテーブルは、複数である限り、必ずしも正確に同じ数のバケットを持っている必要はありません。

Hiveは、データがテーブル定義のバケットに適合しているかどうかを検証せず、クエリ中に例外が発生した場合にのみエラーを報告することに注意してください。したがって、より良い方法は、実行する作業のバレルをHiveに分割するhive.enforce.bucketingことです(setプロパティはtrueです)。

Hive DDL

1.テーブルを作成します

  • CREATE TABLE:指定された名前でテーブルを作成するために使用されます。同じ名前のテーブルがすでに存在する場合、ユーザーはIF NOTEXISTオプションを使用して例外を無視できます。
  • EXTERNAL:このキーワードを使用すると、ユーザーは外部テーブルを作成し、テーブルの作成中に実際のデータ(LOCATION)へのパスを指定できます。
  • コメント:テーブルとフィールドの説明を追加できます。
  • 行形式:ユーザーは、SerDeをカスタマイズするか、テーブルを作成するときに組み込みのSerDeを使用できます。
  • STORED AS:ファイルデータがプレーンテキストの場合は、STORED AS TEXTFILEを使用します。データを圧縮する必要がある場合は、STORED ASSEQUENCEを使用します。
  • LIKE:ユーザーが既存のテーブル構造をコピーできるようにしますが、データはコピーできません。
hive> CREATE TABLE empty key value store 
LIKE key value store;

CREATE TABLE ASSELECTを使用してテーブルを作成することもできます。例は次のとおりです。

Hive> CREATE TABLE new key value store 
	ROW FORMAT 
SERDE "org.apache.Hadoop.hive.serde2.columnar.ColumnarSerDe" 
	STORED AS RCFile 
	AS 
SELECT (key % 1024) new_key, concat(key, value) key_value_pair 
FROM key_value_store 
SORT BY new_key, key_value_pair;

2.テーブルを変更します

テーブル名を変更するための構文は次のとおりです。

hive> ALTER TABLE old_table_name RENAME TO new_table_name;

列名を変更するための構文は次のとおりです。

ALTER TABLE table_name CHANGE (COLUMN) old_col_name new_col_name column_type 
[COMMENT col_comment) (FIRST|AFTER column_name)

上記の構文では、列名、データタイプ、コメント、列の位置、およびそれらの任意の組み合わせを変更できます。テーブルの作成後に新しい列を追加する場合は、次の構文を使用します。

hive> ALTER TABLE pokes ADD COLUMNS (new_col INT COMMENT 'new col comment');

3.テーブルを削除します

DROP TABLEステートメントは、テーブルデータとメタデータを削除するために使用されます。外部テーブルの場合、メタストア内のメタデータのみが削除され、外部データは保存されません。例は次のとおりです。

drop table my_table;

MySQLと同様に、テーブルデータのみを削除してテーブル構造を保持する場合は、TRUNCATEステートメントを使用します。

TRUNCATE TABLE my_table;

4.テーブルを挿入します

(1)テーブルにデータをロードします

相対パスの例は次のとおりです。

hive> LOAD DATA LOCAL INPATH ’./exarnples/files/kvl.txt ’ OVERWRITE INTO 
TABLE pokes;
(2)クエリ結果をHiveに挿入します

クエリ結果をHDFSファイルシステムに書き込みます。

INSERT OVERWRITE TABLE tablenamel [PARTITION (partcoll=val1, partcol2=val2 ... )] 
select_statement1 FROM from_statement

これは基本モードであり、複数挿入モードと自動パーティションモードがありますが、ここでは説明しません。

Hive DML

1.基本的な選択操作

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference 
[WHERE where_condition] 
[GROUP BY col_list [HAVING condition]] 
[ CLUSTER BY col_list 
| [DISTRIBUTE BY col_list] [SORT BY | ORDER BY col_list] 
]
[LIMIT number]
  • ALLオプションとDISTINCTオプションを使用して、重複レコードの処理を区別します。デフォルトはALLで、これはすべてのレコードを照会することを意味し、DISTINCTは重複レコードを削除することを意味します
  • WHERE条件:従来のSQLのwhere条件と同様に、AND、OR、BETWEEN、IN、NOTINなどをサポートします。
  • ORDERBYとSORTBYの違い:ORDER BYは、1つのReduceタスクのみを使用するグローバルソートを指しますが、SORTBYはマシン上でのみソートします
  • LIMIT:SELECT * FROM tl LJMIT5など、クエリするレコードの数を制限できます。また、Topkクエリも実装できます。たとえば、次のクエリステートメントでは、販売レコードが最も多い5人の営業担当者にクエリを実行できます。
SET mapred.reduce.tasks = 1 
SELECT * FROM test SORT BY amount DESC LIMIT 5
  • REGEX列の仕様:selectステートメントは、通常の式を使用して列を選択できます。次のステートメントは、dsとhrを除くすべての列を照会します。
SELECT `(ds|hr)?+.` FROM test

2.表に参加する

join_table:
table_reference (INNER] JOIN table_factor (join_condition]
| table_reference {LEFTIRIGHTjFULL} (OUTER] JOIN table_reference join_ condition
| table_reference LEFT SEM JOIN table_reference join_condition
| table_reference CROSS JOIN table_reference (join_condition] (as of Hive 0.10)
table reference:
table_factor
| join_table
table_factor:
tbl_name [alias]
| table_subquery alias
| (table_references)
join_condition:
on expression
  • Hiveは、等結合、外部結合、および左半結合のみをサポートします(バージョン2.2.0以降、非等価結合がサポートされます)。
  • 次のように、3つ以上のテーブルを接続できます。
select a.val, b.val,c.val 
from a 
join b 
on (a.key=b.key1) 
join c 
on(c.key = b.key2);
  • 接続内の複数のテーブルの結合キーが同じである場合、接続は単一のMap / Reduceタスクに変換されます
select a.val,b.val,c.val 
from a 
join b 
on (a.key=b.key1) 
join c 
on(c.key=b.key1);
  • 結合時に大きなテーブルを最後に配置します。Reduceは、結合シーケンスの最後のテーブルを除くすべてのテーブルのレコードをキャッシュし、最後のテーブルを介して結果をファイルシステムにシリアル化します。
  • 結合の出力を制限する場合は、フィルター条件をwhere句に書き込むか、join句に書き込む必要があります。
  • ただし、テーブルパーティションがあります。たとえば、以下の最初のSQLステートメントに示すように、テーブルcに対応するレコードがテーブルdに見つからない場合、テーブルdのすべての列に列dsを含むNULLがリストされます。つまり、joinは、テーブルcの結合キーに一致するものが見つからないテーブルdのすべてのレコードをフィルタリングします。このようにして、LEFT OUTERはクエリ結果をWHERE句とは無関係にします。解決策は、結合時にパーティションを指定することです(以下の2番目のSQLステートメントを参照)。
--第一个 SQL 语句
SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key) 
WHERE a.ds='2010-07-07' AND b.ds='2010-07-07'
-- 第二个 SQL 语句
SELECT c.val, d.val FROM c LEFT OUTER JOIN d 
ON (c.key=d.key AND d.ds=2009-07-07AND c.ds='2009-07-07')
  • 左半結合は、in / exitsサブクエリのより効率的な実装です。join句の右側のテーブルは、条件をフィルタリングするためにon句でのみ設定でき、where句、select句、またはその他のメソッドではフィルタリングできません。
	SELECT a.key, a.value
 FROM a 
	WHERE a.key in 
	(SELECT b.key FROM B); 
 --可以被重写为:
	SELECT a.key, a.val 
	FROM a LEFT SEMI JOIN b on (a.key = b.key)

3、HiveSQL実行原理図

優れたHiveSQLと不十分に記述されたHiveSQLは、基盤となるコンピューティングとリソースの使用において、数百回、場合によっては数千回、または数万回異なる可能性があることは誰もが知っています。

リソースの浪費に加えて、Hive SQLの不適切な使用は、結果が得られずに数時間または10時間も実行される可能性があります。したがって、HiveSQLの実行プロセスと原理を深く理解することが非常に必要です。

例として、グループごとのステートメント実行図を取り上げます。

ビジネスの背景を想定します。各都市でのiPhone7の顧客の分布、つまり、どの都市が最も多く購入し、どれが最も少ないかを分析します。

select city,count(order_id) as iphone7_count from orders_table where day='201901010' and cat_name='iphone7' group by city;

基盤となるMapReduce実行プロセス:

ステートメント実行原理図によるハイブグループ
Hive SQLのgroupbyステートメントには、データの再配布と配布が含まれるため、その実行プロセスには、MapReduceタスクの実行プロセスが完全に含まれます。

(1)入力フラグメント

group byステートメントの入力ファイルは、day = 20170101のパーティションファイルのままであり、入力フラグメンテーションプロセスと番号はselectステートメントと同じであり、128MB、128MB、および44MBの3つのフラグメントファイルにも分割されます。

(2)マップステージ

Hadoopクラスターは3つのマップタスクを開始して、対応する3つのシャードファイルを処理します。各マップタスクは、対応するシャードファイルの各行を処理し、製品カテゴリがiPhone7であるかどうかを確認します。そうである場合、出力は次のようになります。 City、1>キーと値のペア。注文数は都市に応じてカウントする必要があるためです(selectステートメントとの違いに注意してください)。

(3)コンバイナーステージ

  • コンバイナステージはオプションです。コンバイナ操作が指定されている場合、Hadoopはマップタスクの地上出力でコンバイナ操作を実行します。利点は、冗長な出力を削除でき、不要な後続の処理とネットワーク送信のオーバーヘッドを回避できることです。
  • この列では、<hz、1>がマップタスク1の出力に2回表示され、コンバイナー操作でそれを<hz、2>にマージできます。
  • コンバイナーの操作にはリスクが伴います。コンバイナーの出力がReduce計算の最終入力に影響を与えないという原則があります。たとえば、計算が合計、最大、最小を見つけることだけである場合、コンバイナを使用できますが、平均計算にコンバイナを使用する場合、最終的な削減計算結果は間違っています。

(4)シャッフルステージ

完全なシャッフルには、パーティション分割、並べ替えとスピル、コピー、マージ、およびその他のプロセスが含まれます。

  • group byステートメントを理解するために、実際には2つの主要なプロセス、つまりパーティショニングとマージがあります。いわゆるパーティショニングは、Hadoopが各Mapタスクの各出力キーと値のペアをReduceタスクに割り当てることを決定する方法です。削減タスクで、複数のマップタスクから同じキー値をマージする方法
  • Hadoopで最も一般的に使用されるパーティショニング方法はHashPartitionerです。つまり、Hadoopは各キーのハッシュ値を取得し、reduceタスクの数に応じてハッシュ値を変調して、対応するreduceを取得します。これにより、同じキーが確実に割り当てられます。同じ削減を行うために、ハッシュ関数は、マップタスクの出力がすべての削減タスクに均等に分散されるようにすることもできます。

(5)フェーズを減らす

reduce関数を呼び出し、各reduceタスクの出力をローカルファイルに保存します

(6)出力ファイル

hadoopは、ReduceTaskタスクの出力ファイルを出力ディレクトリにマージします

4、まとめ

HiveSQLの実行原理を紹介しました。もちろん、その理由と理由を知る必要があります。Hiveの実行原理を理解することは、効率的なSQLを作成するための前提条件であり、基礎です。これは、Hive SQL最適化手法を習得するための基盤でもあります。次に、Hive最適化の実践に入ります。

おすすめ

転載: blog.csdn.net/BeiisBei/article/details/109005996