4

私は AWS EMR 経由で Hive を実行しており、ログ データを頻繁に S3 に解析するジョブフローがあります。解析済みの Hive テーブルに動的パーティション (日付とログ レベル) を使用しています。

数ギガバイトのデータと多くのパーティションがある場合、解析が完了した後に Hive がデータをテーブルにロードするときに、今、永遠にかかっていることの 1 つです。

Loading data to table default.logs partition (dt=null, level=null)
    ...
    Loading partition {dt=2013-08-06, level=INFO}
    Loading partition {dt=2013-03-12, level=ERROR}
    Loading partition {dt=2013-08-03, level=WARN}
    Loading partition {dt=2013-07-08, level=INFO}
    Loading partition {dt=2013-08-03, level=ERROR}
    ...

    Partition default.logs{dt=2013-03-05, level=INFO} stats: [num_files: 1, num_rows: 0, total_size: 1905, raw_data_size: 0]
    Partition default.logs{dt=2013-03-06, level=ERROR} stats: [num_files: 1, num_rows: 0, total_size: 4338, raw_data_size: 0]
    Partition default.logs{dt=2013-03-06, level=INFO} stats: [num_files: 1, num_rows: 0, total_size: 828250, raw_data_size: 0]
    ...
    Partition default.logs{dt=2013-08-14, level=INFO} stats: [num_files: 5, num_rows: 0, total_size: 626629, raw_data_size: 0]
    Partition default.logs{dt=2013-08-14, level=WARN} stats: [num_files: 4, num_rows: 0, total_size: 4405, raw_data_size: 0]

この問題を克服し、このステップの読み込み時間を短縮する方法はありますか?

Hive がアーカイブされたパーティションの読み込みをスキップすることを期待して、バケット ライフサイクル ルールを介して古いログを Glacier にアーカイブしようとしました。まあ、これでも S3 Hive でファイル (パス) が表示されたままになるため、とにかくアーカイブされたパーティションが認識されるため、パフォーマンスは向上しません。

更新 1

データのロードは、動的に分割されたテーブルにデータを挿入するだけで実行されます

INSERT INTO TABLE logs PARTITION (dt, level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, dt, level
FROM new_logs ;

解析されていないログを含む 1 つのテーブルから

CREATE EXTERNAL TABLE new_logs (
  dt STRING,
  time STRING,
  thread STRING,
  level STRING,
  logger STRING,
  identity STRING,
  message STRING,
  logtype STRING,
  logsubtype STRING,
  node STRING,
  storageallocationstatus STRING,
  nodelist STRING,
  userid STRING,
  nodeid STRING,
  path STRING,
  datablockid STRING,
  hash STRING,
  size STRING,
  value STRING,
  exception STRING,
  version STRING
)
PARTITIONED BY (
  server STRING,
  app STRING
)
ROW FORMAT
  DELIMITED
  FIELDS TERMINATED BY '\t'
STORED AS
  INPUTFORMAT 'org.maz.hadoop.mapred.LogFileInputFormat'
  OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION 's3://my-log/logs/${LOCATION}' ;

新しい(解析された)テーブルに

CREATE EXTERNAL TABLE logs (
  time STRING,
  thread STRING,
  logger STRING,
  identity STRING,
  message STRING,
  logtype STRING,
  logsubtype STRING,
  node STRING,
  storageallocationstatus STRING,
  nodelist STRING,
  userid STRING,
  nodeid STRING,
  path STRING,
  datablockid STRING,
  hash STRING,
  size STRING,
  exception STRING,
  value STRING,
  server STRING,
  app STRING,
  version STRING
)
PARTITIONED BY (
  dt STRING,
  level STRING
)
ROW FORMAT
  DELIMITED
  FIELDS TERMINATED BY '\t'
  LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION 's3://my-log/parsed-logs' ;

入力形式 (LogFileInputFormat) は、ログ エントリを目的のログ形式に解析する役割を果たします。

更新 2

次のことを試してみると

INSERT INTO TABLE logs PARTITION (dt, level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, dt, level
FROM new_logs
WHERE dt > 'some old date';

Hive は引き続きすべてのパーティションをログにロードします。一方、次のような静的パーティショニングを使用する場合

INSERT INTO TABLE logs PARTITION (dt='some date', level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, level
FROM new_logs
WHERE dt = 'some date';

Hive は関連するパーティションのみをロードしますが、new_logs に存在すると思われる日付ごとに 1 つのクエリを作成する必要があります。通常、new_logs には今日と昨日のログ エントリのみが含まれますが、古いエントリも含まれる場合があります。

現時点では、静的パーティション分割が私の選択の解決策ですが、私の問題に対する他の (より良い) 解決策はありませんか?

4

2 に答える 2

1

この遅い段階で、Hive は各パーティション用に作成したファイルを取得し、それを一時ディレクトリから永続ディレクトリに移動します。これは、Move Operator と呼ばれる「explain extended」で確認できます。

そのため、パーティションごとに 1 回の移動とメタストアへの更新が行われます。私は EMR を使用しませんが、ファイルを S3 に移動するこの行為は、移動する必要がある各ファイルのレイテンシーが高いと推測します。

あなたが書いたものから明らかでないのは、実行するたびに全負荷を実行しているかどうかです。たとえば、なぜ 2013-03-05 パーティションがあるのでしょうか? この古い日付を含む新しいログ データを取得していますか? このデータが既にログ テーブルにある場合は、insert ステートメントを次のように変更する必要があります。

SELECT fields
FROM new_logs
WHERE dt > 'date of last run';

こうすれば、移動するバケットとファイルをいくつかだけ取得できます。new_logs からこの余分なデータをすべてスキャンするのはやはり無駄ですが、new_logs を分割することで解決できます。

于 2013-08-18T08:31:57.053 に答える
0

AWS は、EMR 3.2.x 以降で HIVE パーティションの復旧時間を 1 桁以上改善しました。

S3 に 20,000 を超えるパーティションを持つ HIVE テーブルがあります。以前のバージョンの EMR では、復旧に最大 80 分かかっていましたが、3.2.x/3.3.x では 5 分未満で復旧できるようになりました。

于 2014-12-24T01:17:42.160 に答える