29

私はそのようにテーブルを定義しました:

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'
4

3 に答える 3

22

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時間のログをクエリできます。

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テーブルの一部になることができる)、ディレクトリ内のすべてのデータを分析するクエリを作成していることがわかる場合は、Optionを選択します。 2.2。

于 2012-07-01T00:11:29.413 に答える
11

同様の問題を解決する必要があるときに、このスレッドに出くわしました。カスタムSerDeを使用して解決することができました。次に、特定のテーブルのファイル名パターンに適用する正規表現をガイドするSerDeプロパティを追加しました。

標準のCSVファイルのみを処理している場合、カスタムSerDeはやり過ぎに見えるかもしれませんが、処理するファイル形式はもっと複雑でした。それでも、Javaを書くことを躊躇しないのであれば、これは非常に実行可能な解決策です。これは、保存場所のデータを再構築できず、不釣り合いに大きいファイルセットの中から非常に特定のファイルパターンを探している場合に特に便利です。

> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string)  
> ROW FORMAT SERDE 'com.something.MySimpleSerDe' 
> WITH SERDEPROPERTIES ( "input.regex" = "*.csv")
> LOCATION '/user/data';
于 2016-08-15T03:08:43.123 に答える
7

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

今のところ最善の策は、別のディレクトリにテーブルを作成し、クエリするファイルをコピーすることです。

于 2012-06-29T22:26:55.113 に答える