回答:
データのパーティション分割は、負荷を水平に分散するためによく使用されます。これにはパフォーマンス上の利点があり、データを論理的に編成するのに役立ちます。例:大きなemployee
テーブルを処理しWHERE
ていて、結果を特定の国または部門に制限する句を使用してクエリを実行する場合。クエリ応答を高速化するには、Hiveテーブルを使用できますPARTITIONED BY (country STRING, DEPT STRING)
。テーブルのパーティション分割により、Hiveがデータストレージを構造化する方法が変わり、Hiveは次のようなパーティション構造を反映するサブディレクトリを作成します
... / employees / country = ABC / DEPT = XYZ。
fromの従業員のクエリ制限の場合country=ABC
、1つのディレクトリの内容のみがスキャンされcountry=ABC
ます。これにより、クエリのパフォーマンスが劇的に向上しますが、それはパーティション分割スキームが一般的なフィルタリングを反映している場合に限られます。パーティショニング機能はHiveで非常に役立ちますが、作成するパーティションが多すぎる設計では一部のクエリが最適化される可能性がありますが、他の重要なクエリにとっては不利益になります。その他の欠点は、パーティションが多すぎることです。ファイルシステムのすべてのメタデータをメモリに保持する必要があるため、不必要に作成される大量のHadoopファイルとディレクトリ、およびNameNodeへのオーバーヘッドです。
バケット化は、データセットをより管理しやすい部分に分解するためのもう1つの手法です。たとえばdate
、トップレベルのパーティションemployee_id
として、およびセカンドレベルのパーティションが小さなパーティションの数が多すぎるために使用しているテーブルがあるとします。代わりに、従業員テーブルをバケットemployee_id
してバケット列として使用すると、この列の値はユーザー定義の数値によってバケットにハッシュされます。同じレコードemployee_id
は常に同じバケットに保存されます。employee_id
の数がバケットの数よりはるかに多いと仮定すると、各バケットには多数のがありemployee_id
ます。テーブルを作成するときに、次のように指定できますCLUSTERED BY (employee_id) INTO XX BUCKETS;
ここで、XXはバケットの数です。バケット化にはいくつかの利点があります。バケットの数は固定されているため、データによって変動しません。2つのテーブルがによってバケット化されている場合employee_id
、Hiveは論理的に正しいサンプリングを作成できます。バケットは、効率的なマップ側の結合などにも役立ちます。
これまでの説明に欠けている詳細がいくつかあります。パーティショニングとバケット化がどのように機能するかをよりよく理解するには、データがハイブに格納される方法を確認する必要があります。テーブルがあるとしましょう
CREATE TABLE mytable (
name string,
city string,
employee_id int )
PARTITIONED BY (year STRING, month STRING, day STRING)
CLUSTERED BY (employee_id) INTO 256 BUCKETS
その後、ハイブは次のようなディレクトリ階層にデータを保存します
/user/hive/warehouse/mytable/y=2015/m=12/d=02
したがって、パーティショニングの際は注意が必要です。たとえば、employee_idでパーティションを作成し、数百万の従業員がいる場合、ファイルシステムに数百万のディレクトリが存在することになります。「カーディナリティ」という用語は、フィールドが持つことができる可能な値の数を指します。たとえば、「国」フィールドがある場合、世界の国は約300であるため、カーディナリティは約300になります。ミリ秒ごとに変化する「timestamp_ms」のようなフィールドの場合、カーディナリティは数十億になる可能性があります。一般に、パーティション化するフィールドを選択するときは、ファイルシステム内のディレクトリが多すぎるため、カーディナリティを高くしないでください。
一方、バケットの数を指定しているため、クラスタリング(別名バケット化)では、ファイルの数が固定されます。ハイブが行うことは、フィールドを取得してハッシュを計算し、そのバケットにレコードを割り当てることです。しかし、256バケットを使用していて、バケットしているフィールドのカーディナリティが低い場合はどうなりますか(たとえば、米国の州であるため、50の異なる値しか使用できません)。データのあるバケットが50個、データのないバケットが206個あります。
誰かがパーティションがクエリしているデータの量を劇的に減らすことができる方法をすでに誰かが述べました。したがって、私の例の表で、特定の日付以降のクエリのみを実行したい場合、年/月/日でパーティション化すると、IOの量が大幅に削減されます。誰かがバケット化によってまったく同じバケット化を持つ他のテーブルとの結合を高速化できる方法についても誰かが言及したと思うので、私の例では、同じemployee_idで2つのテーブルを結合する場合、ハイブはバケットごとに結合バケットを実行できます(さらに優れています) O_(n)として知られる線形時間で動作する、すでにソートされているマージソートパーツをマージするため、それらがすでにemployee_idでソートされている場合。
したがって、フィールドのカーディナリティが高く、データがバケット間で均等に分散されている場合は、バケット化が適切に機能します。パーティション化は、パーティション化フィールドのカーディナリティが高すぎない場合に最適に機能します。
また、順序を付けて複数のフィールドにパーティション化でき(年/月/日が良い例です)、バケット化できるフィールドは1つだけです。
私はこの質問に答えるのが遅いと思いますが、それは私のフィードで増え続けます。
Navneetは素晴らしい答えを提供してくれました。視覚的に追加します。
パーティション化は、WHERE句で使用した場合、データの排除に役立ちます。バケット化は、各パーティションのデータを複数のファイルに編成するのに役立ちます。これにより、同じデータセットが常に同じバケットに書き込まれます。列の結合に役立ちます。
たとえば、name、server_date、some_col3、some_col4、some_col5という5つの列を持つテーブルがあるとします。server_dateでテーブルをパーティション分割し、nameカラムで10バケットにバケット化した場合、ファイル構造は次のようになります。
ここで、server_date = xyzはパーティションであり、000ファイルは各パーティションのバケットです。バケットはいくつかのハッシュ関数に基づいて計算されるため、name = Sandyの行は常に同じバケットに入ります。
ハイブのパーティション分割:
パーティションは、テーブルの列の値に基づいて、大量のデータを複数のスライスに分割します。
世界中の人々の情報を、約500クロアのエントリにまたがる196か国以上に保存しているとします。特定の国(バチカン市国)の人々にクエリを実行する場合、パーティショニングがない場合、国の千のエントリを取得する場合でも、500クロアのエントリすべてをスキャンする必要があります。国に基づいてテーブルをパーティション分割する場合、1つの国パーティションのみのデータをチェックするだけで、クエリプロセスを微調整できます。Hiveパーティションは、列値用に別のディレクトリを作成します。
長所:
短所:
ハイブバケット:
バケット化は、データをより扱いやすい、または同等の部分に分解します。
パーティション化を使用すると、列の値に基づいて複数の小さなパーティションを作成できる可能性があります。バケット化を行う場合、データを保存するバケットの数を制限しています。この数は、テーブル作成スクリプト中に定義されます。
長所
短所
に入る前にBucketing
、何であるかを理解する必要Partitioning
があります。以下の表を例として取り上げます。初心者レベルの理解のために、以下の例では12個のレコードしか示していません。リアルタイムのシナリオでは、何百万ものレコードがある場合があります。
PARTITIONING
---------------------
Partitioning
は、データのクエリ中にパフォーマンスを取得するために使用されます。たとえば、上記の表で、以下のSQLを作成する場合、テーブル内のすべてのレコードをスキャンする必要があるため、パフォーマンスが低下し、オーバーヘッドが増加します。
select * from sales_table where product_id='P1'
全テーブルスキャンを回避し、関連するレコードのみを読み取るためproduct_id='P1'
に、product_id
列に基づいて複数のファイルに分割(ハイブテーブルのファイルを分割)できます。これによりハイブテーブルのファイルには、2つのファイルと1に分割されますproduct_id='P1'
として、他のproduct_id='P2'
。上記のクエリを実行すると、product_id='P1'
ファイルのみがスキャンされます。
../hive/warehouse/sales_table/product_id=P1
../hive/warehouse/sales_table/product_id=P2
パーティションを作成するための構文を以下に示します。product_id
以下の構文では、パーティション化されていない列と共に列定義を使用しないでください。これはpartitioned by
条項のみにあるべきです。
create table sales_table(sales_id int,trans_date date, amount int)
partitioned by (product_id varchar(10))
短所:パーティション分割中は注意が必要です。つまり、パーティション化されたファイルの数が増え、のオーバーヘッドが増えるため、繰り返し値の数が非常に少ない列(特に主キー列)には使用しないでくださいName node
。
BUCKETING
------------------
Bucketing
はcons
、パーティション設定のセクションで述べたものを克服するために使用されます。これは、列に繰り返し値が非常に少ない場合に使用する必要があります(例-主キー列)。これは、RDBMSの主キー列のインデックスの概念に似ています。この表ではSales_Id
、バケット化のための列を取得できます。sales_id
列を照会する必要がある場合に役立ちます。
以下はバケットの構文です。
create table sales_table(sales_id int,trans_date date, amount int)
partitioned by (product_id varchar(10)) Clustered by(Sales_Id) into 3 buckets
ここでは、パーティションの上にあるさらにいくつかのファイルにデータをさらに分割します。
3
バケットを指定したので、バケットはそれぞれ3つのファイルに分割されますproduct_id
。内部的に使用modulo operator
して、それぞれsales_id
を格納するバケットを決定します。例えば、のためにproduct_id='P1'
、sales_id=1
中に格納される000001_0ファイル(すなわち、1%3 = 1)sales_id=2
に格納される000002_0ファイル(すなわち、2%3 = 2)sales_id=3
に格納される000000_0ファイル(すなわち、3% 3 = 0)など
hashCode()
、文字列のJava をハッシュ関数として使用しますか?プログラマーはハッシュ関数を選択できますか?
以下の理由により、Hiveテーブルでパーティションを使用することを強くお勧めします-
例:-
入力ファイル(100 GB)がtemp-hive-tableにロードされ、さまざまな地域の銀行データが含まれていると想定します。
パーティションのないハイブテーブル
Insert into Hive table Select * from temp-hive-table
/hive-table-path/part-00000-1 (part size ~ hdfs block size)
/hive-table-path/part-00000-2
....
/hive-table-path/part-00000-n
このアプローチの問題は、このテーブルで実行するクエリのデータ全体をスキャンすることです。応答時間は、パーティショニングとバケット化が使用される他のアプローチと比較して高くなります。
パーティション付きハイブテーブル
Insert into Hive table partition(country) Select * from temp-hive-table
/hive-table-path/country=US/part-00000-1 (file size ~ 10 GB)
/hive-table-path/country=Canada/part-00000-2 (file size ~ 20 GB)
....
/hive-table-path/country=UK/part-00000-n (file size ~ 5 GB)
長所-特定の地理トランザクションのデータのクエリに関しては、データにすばやくアクセスできます。短所-データの挿入/クエリは、各パーティション内でデータを分割することによってさらに改善できます。下記のバケットオプションをご覧ください。
パーティションとバケットを備えたハイブテーブル
注:「CLUSTERED BY(Partiton_Column)」を使用して5つのバケットにハイブテーブル.....を作成します
Insert into Hive table partition(country) Select * from temp-hive-table
/hive-table-path/country=US/part-00000-1 (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-2 (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-3 (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-4 (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-5 (file size ~ 2 GB)
/hive-table-path/country=Canada/part-00000-1 (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-2 (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-3 (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-4 (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-5 (file size ~ 4 GB)
....
/hive-table-path/country=UK/part-00000-1 (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-2 (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-3 (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-4 (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-5 (file size ~ 1 GB)
長所-より高速な挿入。より高速なクエリ。
短所-バケット化すると、より多くのファイルが作成されます。特定のケースでは、多くの小さなファイルで問題が発生する可能性があります
これが役立つことを願っています!!