web-dev-qa-db-ja.com

Hiveで外部テーブルを作成するときに、ディレクトリ内の特定のファイルに場所を指定できますか?

テーブルを次のように定義しました:

create external table PageViews (Userid string, Page_View string)
partitioned by (ds string)
row format as delimited fields terminated by ','
stored as textfile location '/user/data';

/ user/dataディレクトリ内のすべてのファイルをテーブルの一部として使用したくない。次のことを行うことはできますか?

location 'user/data/*.csv'
23
George TeVelde

似たような問題を解決するときに、このスレッドに出くわしました。カスタムSerDeを使用して解決できました。次に、特定のテーブルのファイル名パターンに適用するRegExをガイドするSerDeプロパティを追加しました。

標準のCSVファイルだけを扱っている場合、カスタムSerDeはやり過ぎに見えるかもしれません。私はもっと複雑なファイル形式を扱っていました。それでも、これは、Javaを書くことにshしないなら、非常に実行可能なソリューションです。保管場所のデータを再構成できず、不均衡に大きいファイルセットの中から非常に具体的なファイルパターンを探している場合に特に役立ちます。

> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string)  
> ROW FORMAT SERDE 'com.something.MySimpleSerDe' 
> WITH SERDEPROPERTIES ( "input.regex" = "*.csv")
> LOCATION '/user/data';
11
NG Algo

Kmosleyが言ったことは本当です。現在のところ、特定のファイルをHiveテーブルの一部として選択することはできません。ただし、それを回避するには2つの方法があります。

オプション1:すべてのcsvファイルを別のHDFSディレクトリに移動し、その上にHiveテーブルを作成できます。うまく機能する場合は、現在のディレクトリ内にすべてのCSVファイルを格納するサブディレクトリ(たとえば、csv)を作成できます。その後、このサブディレクトリの上にHiveテーブルを作成できます。親ディレクトリの上に作成されたHiveテーブルには、サブディレクトリからのデータが含まれないことに注意してください。

オプション2:INPUT__FILE__NAMEという仮想列を使用するようにクエリを変更できます。

クエリは次のようになります。

SELECT 
   *
FROM
   my_table
WHERE
   INPUT__FILE__NAME LIKE '%csv';

このアプローチの悪影響は、特定のファイルだけを気にしている場合でも、Hiveクエリがディレクトリ内に存在するデータ全体を解約する必要があることです。クエリは、INPUT__FILE__NAMEを使用した述語に基づいてファイルを除外しません。マップフェーズ中にINPUT__FILE__NAMEを使用して述語と一致しないレコードを除外します(その結果、特定のファイルからすべてのレコードを除外します)が、マッパーは不要なファイルでも実行されます。正しい結果が得られますが、パフォーマンスオーバーヘッドはおそらくわずかですが、おそらくわずかです。

このアプローチの利点は、テーブルに複数のファイルがあり、いくつかのクエリとそのファイルのサブセットでそのテーブル(またはそのパーティション)からすべてのファイルをクエリする機能が必要な場合、同じHiveテーブルを使用できることです他のクエリ。 INPUT__FILE__NAME仮想列を使用してそれを実現できます。例として、HDFSディレクトリのパーティション/user/Hive/warehouse/web_logs/が次のようになっている場合:

/user/Hive/warehouse/web_logs/dt=2012-06-30/
   /user/Hive/warehouse/web_logs/dt=2012-06-30/00.log
   /user/Hive/warehouse/web_logs/dt=2012-06-30/01.log
   .
   .
   .
   /user/Hive/warehouse/web_logs/dt=2012-06-30/23.log

テーブル定義が次のようになっているとしましょう:

CREATE EXTERNAL TABLE IF NOT EXISTS web_logs_table (col1 STRING)
PARTITIONED BY (dt STRING)
LOCATION '/user/Hive/warehouse/web_logs';

適切なパーティションを追加したら、次のようなクエリを使用してパーティション内のすべてのログをクエリできます。

SELECT
   *
FROM
   web_logs_table w
WHERE
   dt='2012-06-30';

ただし、1日の最初の1時間からのみログを気にする場合は、次のようなクエリを使用して最初の1時間のログをクエリできます。

SELECT
   *
FROM
   web_logs_table w
WHERE 
   dt ='2012-06-30'
   AND INPUT__FILE__NAME='00.log';

別の同様の使用例は、異なるドメインからのWebログを含むディレクトリであり、さまざまなクエリは異なるドメインセットのログを分析する必要があります。クエリは、INPUT__FILE__NAME仮想列を使用してドメインを除外できます。

上記の両方のユースケースで、時間またはドメインにサブパーティションを設定すると、仮想列を使用せずに問題を解決できます。ただし、サブパーティションを作成しないことを要求する設計上のトレードオフが存在する場合があります。その場合、ほぼ間違いなく、INPUT__FILE__NAME仮想列を使用するのが最善の策です。

2つのオプションの決定:

それは本当にあなたのユースケースに依存します。 Hiveテーブルから除外しようとしているファイルを気にしない場合は、おそらくオプション2を使用するのはやり過ぎです。ディレクトリ構造を修正し、関心のあるファイルを含むディレクトリの上にHiveテーブルを作成する必要があります。 。

現在除外しているファイルが他のファイルと同じ形式に従うため(すべてが同じHiveテーブルの一部になることができます)、ディレクトリ内のすべてのデータを分析するクエリを作成していることがわかります。 2。

20
Mark Grover

いいえ、現在はできません。 Hiveテーブルに含まれるファイルの正規表現選択を許可するJIRAチケットがあります( https://issues.Apache.org/jira/browse/Hive-951 )。

現時点では、別のディレクトリにテーブルを作成し、クエリするファイルをコピーすることをお勧めします。

7
kmosley