web-dev-qa-db-ja.com

Hive外部テーブルの最初の行をスキップ

ClouderaのHiveバージョンを使用して、最初の列に列名を含むcsvファイル上に外部テーブルを作成しようとしています。これを行うために使用しているコードを次に示します。

CREATE EXTERNAL TABLE Test ( 
  RecordId int, 
  FirstName string, 
  LastName string 
) 
ROW FORMAT serde 'com.bizo.Hive.serde.csv.CSVSerde' 
WITH SerDeProperties (  
  "separatorChar" = ","
) 
STORED AS TEXTFILE 
LOCATION '/user/File.csv'

サンプルデータ

RecordId,FirstName,LastName
1,"John","Doe"
2,"Jane","Doe"

誰でも最初の行をスキップする方法を手伝ってくれますか、中間ステップを追加する必要がありますか?

45
Rick Gittins

データのヘッダー行は、Hiveの永続的な頭痛の種です。 Hiveのソースを変更する以外に、中間ステップなしでは逃げられないと思います。 (編集:これはもはや真実ではありません。以下の更新を参照してください)

残念ながら、それはあなたの質問に答えます。完全を期すための中間ステップのアイデアをいくつか紹介します。

テーブルにアクセスするすべてのクエリでヘッダー行をフィルターで除外する場合は、データのロードに余分な手順を追加せずに脱出できます。残念ながら、これは他のほぼすべての場所に追加のセットを追加します。また、ヘッダー行がスキーマに違反している場合は、巧妙/乱雑になる必要があります。このアプローチを採用する場合、この行をフィルター処理しやすくするカスタムSerDeを作成することを検討してください。残念ながら、SerDeは行を完全に削除することはできません(または、解決策になる可能性があります)。nullのようなものを返す必要があります。読み取りが苦痛になり、読み取りは書き込みよりもはるかに一般的である傾向があるため、ヘッダー行を処理するために実際にこのアプローチが取られるのを見たことはありません。 one-ofテーブルを扱っている場合、またはヘッダー行が多くの不正な行の中の1行にすぎない場合は、場所があるかもしれません。

データフィルタリングの最初の行を削除するバリエーションを使用して、このフィルタリングを1回実行できます。 WHEREステートメントのINSERT句はそれを行います。 sedのようなユーティリティを使用して、それを取り除くことができます。両方のアプローチが取られているのを見てきました。どのアプローチを採用するかにはトレードオフがあり、どちらもヘッダー行を処理するための真の方法ではありません。残念ながら、これらのアプローチは両方とも時間がかかり、データの一時的な複製が必要です。別のアプリケーションのヘッダー行が絶対に必要な場合、複製は永続的です。

更新:

Hive v0.13.0以降では、skip.header.line.countを使用できます。テーブルの作成中に同じものを指定することもできます。例えば:

create external table testtable (name string, message string)
row format delimited 
fields terminated by '\t' 
lines terminated by '\n' 
location '/testtable'
tblproperties ("skip.header.line.count"="1");
70
Daniel Koverman

ダニエルからの回答がありますが、OpenCSVSerdeを使用していくつかのカスタマイズが可能です。

CREATE EXTERNAL TABLE `mydb`.`mytable`(
    `product_name` string,
    `brand_id` string,
    `brand` string,
    `color` string,
    `description` string,
    `sale_price` string)
PARTITIONED BY (
    `seller_id` string)
ROW FORMAT SERDE
    'org.Apache.hadoop.Hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
    'separatorChar' = '\t',
    'quoteChar' = '"',
    'escapeChar' = '\\')
STORED AS INPUTFORMAT
    'org.Apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
    'org.Apache.hadoop.Hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
    'hdfs://namenode.com:port/data/mydb/mytable'
TBLPROPERTIES (
    'serialization.null.format' = '',
    'skip.header.line.count' = '1')

これにより、セパレータ、引用文字、エスケープ文字、ヌル処理、ヘッダー処理を完全に制御できます。

here および here を見てください。

12
Nirmal

クエリにプロパティの下に追加するだけで、レコードがロードされない最初のヘッダーまたは行intがスキップされるか、スキップされます。

これを試して

tblproperties ("skip.header.line.count"="1");
8
Manish
create external table table_name( 
Year int, 
Month int,
column_name data_type ) 
row format delimited fields terminated by ',' 
location '/user/user_name/example_data' TBLPROPERTIES('serialization.null.format'='', 'skip.header.line.count'='1');
2
Aman Mundra

skip.header.line.countは機能しますが、このテーブルへのアクセスにアクセスする外部ツールがある場合、それらの行をスキップせずに実際のデータが表示されます

2
itsavy

ヘッダー付きのテーブルをすでに作成している人のために。同じものに対するalterコマンドを次に示します。これは、すでにテーブルがあり、最初の行を削除および再作成せずに無視する場合に便利です。また、TBLPROPERTIESのオプションとしてALTERに慣れるのに役立ちます。

ALTER TABLE tablename SET TBLPROPERTIES ("skip.header.line.count"="1");

ROW FORMAT serde 'com.bizo.Hive.serde.csv.CSVSerde'で動作するかどうかはわかりませんが、ROW FORMAT DELIMITED FIELDS TERMINATED BY '、'に似ているはずです。
最初の行は通常の行と同様に扱われます。ただし、最初のフィールドはINTに失敗するため、最初の行のすべてのフィールドはNULLに設定されます。修正するための中間ステップは1つだけです。

INSERT OVERWRITE TABLE Test
SELECT * from Test WHERE RecordId IS NOT NULL

唯一の欠点は、元のcsvファイルが変更されることです。役に立てば幸いです。 GL!

1
www

私もこれに苦労し、Hiveに最初の行をスキップするように指示する方法が見つかりませんでした。 Greenplumで。そのため、最終的にはファイルから削除する必要がありました。例えば「cat File.csv | grep -v RecordId> File_no_header.csv」

0
Atanas