Hiveでのテーブルのパーティション化とバケット化の違いは何ですか?


129

テーブルの列で両方が実行されることはわかっていますが、各操作はどのように異なりますか。

回答:


247

データのパーティション分割は、負荷を水平に分散するためによく使用されます。これにはパフォーマンス上の利点があり、データを論理的に編成するのに役立ちます。:大きな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は論理的に正しいサンプリングを作成できます。バケットは、効率的なマップ側の結合などにも役立ちます。


4
Navneetに感謝します。しかし、パーティショニングでバケット化がどのように行われるかを詳しく説明できますか?CLUSED BY句で32個のバケットを指定し、CREATE TABLEステートメントにPartitioning句も含まれている場合、パーティションとバケットを一緒に管理するにはどうすればよいでしょうか。パーティションの数は32に制限されますか?または、パーティションごとに32個のバケットが作成されますか?すべてのバケットはHDFSファイルですか?
sgsi 2015

12
ハイブテーブルには、パーティション化とバケット化の両方を設定できます。パーティション句に基づいて、パーティションごとに32個のバケットが作成されます。はいHDFSファイル。
Navneet Kumar

7
@sgsiパーティションはフォルダ、バケットはファイルです。
16

12
参考までに、この回答はプログラミングハイブ(O'Reilly、2012年)のテキストから派生しています。
ianmcook 2016年

1
このリンクは役に立ちました。それはこの答えにさらに価値を加える情報を持っています。linkedin.com/pulse/...
アレックス・ラジKaliamoorthy

129

これまでの説明に欠けている詳細がいくつかあります。パーティショニングとバケット化がどのように機能するかをよりよく理解するには、データがハイブに格納される方法を確認する必要があります。テーブルがあるとしましょう

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つだけです。


例でSORTED-BYを使用してCLUSTERED-BYの動作を説明できますか?私の例のとおり、SORTED-BYは何もしないことがわかりました。何か不足していますか?
Jagadish Talluri 2016年

2
CLUSTERED BY x、yは、DISTRIBUTE BY x、y SORT BY x、y(cwiki.apache.org/confluence/display/Hive/…を参照)を書くのに似ているので、SORT BYをCLUSTERED BYに追加しても効果はありません。
Roberto Congiu

興味深いことに、selectクエリでの使用について同意します。しかし、なぜ人々はクラスタ化され、テーブル作成ステートメントで一緒にソートされているのか疑問に思いました。DDLでSORTED BYに意味がない場合、なぜこのキーワードが存在するのですか?わかりませんでした。
Jagadish Talluri 2016年

SORTED BYは、DISTRIBUTED BYと一緒に使用するためのものです。たとえば、ユーザーIDで配布し、バケット内の時間で並べ替えることができます。CLUSTER BYは、SORTED BYとDISTRIBUTED BYの句が同じ場合の単なるショートカットです。私が考えられる唯一のことは、x、yで配布し、x、y、zで並べ替えている場合です
Roberto Congiu

「1つのフィールドにしかバケットできない」という意味がわかりません。ハッシュ関数がすべてのフィールドを取得してそれらを組み合わせるだけで、複数のフィールドでバケット化することは可能だと思います。
Istvan

18

私はこの質問に答えるのが遅いと思いますが、それは私のフィードで増え続けます。

Navneetは素晴らしい答えを提供してくれました。視覚的に追加します。

パーティション化は、WHERE句で使用した場合、データの排除に役立ちます。バケット化は、各パーティションのデータを複数のファイルに編成するのに役立ちます。これにより、同じデータセットが常に同じバケットに書き込まれます。列の結合に役立ちます。

たとえば、name、server_date、some_col3、some_col4、some_col5という5つの列を持つテーブルがあるとします。server_dateでテーブルをパーティション分割し、nameカラムで10バケットにバケット化した場合、ファイル構造は次のようになります。

  1. server_date = xyz
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0

ここで、server_date = xyzはパーティションであり、000ファイルは各パーティションのバケットです。バケットはいくつかのハッシュ関数に基づいて計算されるため、name = Sandyの行は常に同じバケットに入ります。


2
上記のRoberto氏によると、カーディナリティ値が非常に高いため、server_dateはパーティショニングを行うのに適した例ではありません。その結果、hdfs内のフォルダーが多すぎます。
Gaurang Shah、2018

ここでは、例としてserver_dateについて説明します。現実の世界では、パーティションは通常、日付を年/月/日に分解することにより、ロベルトが描いたように発生します。それはそうあるべきである方法です。
Priyesh 2018

17

ハイブのパーティション分割:

パーティションは、テーブルの列の値に基づいて、大量のデータを複数のスライスに分割します。

世界中の人々の情報を、約500クロアのエントリにまたがる196か国以上に保存しているとします。特定の国(バチカン市国)の人々にクエリを実行する場合、パーティショニングがない場合、国の千のエントリを取得する場合でも、500クロアのエントリすべてをスキャンする必要があります。国に基づいてテーブルをパーティション分割する場合、1つの国パーティションのみのデータをチェックするだけで、クエリプロセスを微調整できます。Hiveパーティションは、列値用に別のディレクトリを作成します。

長所:

  1. 実行負荷を水平に分散
  2. データ量が少ないパーティションの場合、クエリの実行が速くなります。たとえば、「バチカン市国」から人口を取得すると、世界の人口全体を検索する代わりに非常に高速に戻ります。

短所:

  1. 小さすぎるパーティションの作成が多すぎる可能性-ディレクトリが多すぎる。
  2. 特定のパーティションの少量のデータに有効です。しかし、大量のデータに対するgroup byなどの一部のクエリは、実行に長い時間がかかります。例えば、中国の人口のグループ化は、バチカン市国の人口のグループ化と比較して長い時間がかかります。データが特定のパーティション値に偏っている場合、パーティションは応答性の問題を解決していません。

ハイブバケット:

バケット化は、データをより扱いやすい、または同等の部分に分解します。

パーティション化を使用すると、列の値に基づいて複数の小さなパーティションを作成できる可能性があります。バケット化を行う場合、データを保存するバケットの数を制限しています。この数は、テーブル作成スクリプト中に定義されます。

長所

  1. 各パーティションのデータ量が等しいため、マップ側での結合はより速くなります。
  2. パーティショニングのようなクエリ応答の高速化

短所

  1. テーブルの作成中にバケット数を定義できますが、等量のデータのロードはプログラマーが手動で行う必要があります。

9

に入る前に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
------------------
Bucketingcons、パーティション設定のセクションで述べたものを克服するために使用されます。これは、列に繰り返し値が非常に少ない場合に使用する必要があります(例-主キー列)。これは、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)など


数値のクラスター化された列の場合、常にバケットの数だけmodをとりますか?文字列値のクラスター化された列の場合hashCode()、文字列のJava をハッシュ関数として使用しますか?プログラマーはハッシュ関数を選択できますか?
Don Smith、

どうやら(そして私の実験によれば)hiveはJavaのhashCode()メソッドのバリエーションを使用しています:github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/…。これはここで言及されました:stackoverflow.com/questions/30594038/…
Don Smith、

3

違いは、バケット化によりファイルが列名で分割され、パーティション化によりファイルがテーブル内の特定の値で分割されることです。

うまくいけば、私はそれを正しく定義しました


0

ここには素晴らしい反応があります。パーティションとバケットの違いを覚えておくために短くしておきたいと思います。

通常、一意性の低い列でパーティションを作成します。そして、最もユニークな列にバケット化します。

例として、国、人名、およびその生体認証IDを持つ世界人口を考える場合の例。ご想像のとおり、countryフィールドは一意性の低い列になり、生体認証IDは最も一意性の高い列になります。したがって、理想的には、国ごとにテーブルを分割し、バイオメトリックIDごとにバケット化する必要があります。


-1

以下の理由により、Hiveテーブルでパーティションを使用することを強くお勧めします-

  • Hiveテーブルへの挿入はより高速である必要があります(パーティションにデータを書き込むために複数のスレッドを使用するため)
  • 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)

長所-より高速な挿入。より高速なクエリ。

短所-バケット化すると、より多くのファイルが作成されます。特定のケースでは、多くの小さなファイルで問題が発生する可能性があります

これが役立つことを願っています!!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.