2013-04-01 52 views
37

我使用的是Cloudera的Hive版本,並嘗試通過包含第一列中的列名稱的csv文件創建外部表。這裏是我用來做到這一點的代碼。Hive外部表跳過第一行

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" 

誰能幫助我如何跳過第一行還是需要增加一箇中間步驟?

+0

我剛開始玩蜂窩自己,從我可以告訴,SERDE上唯一一個行通過行的基礎上工作,所以它可能不是沒有一些中間是可能的。如果我能想到什麼,我會在這裏發佈。我也對解決方案感興趣。 – nolanpro

回答

49

數據中的標題行在Hive中是永久的頭痛。在修改Hive源代碼之前,我相信如果沒有中間步驟,就無法脫身。 (編輯:這不再是真實的,請參閱下面的更新)

不幸的是,這回答你的問題。我會針對完整性的中間步驟提出一些想法。

如果您願意在觸及表的每個查詢中篩選出標題行,那麼您可以在數據加載中不需要額外的步驟。不幸的是,這在其他地方增加了一個額外的設置。當標題行違反了你的模式時,你將不得不變得聰明/雜亂。如果你採用這種方法,你可以考慮編寫一個自定義的SerDe,使得這一行更容易過濾。不幸的是,SerDe無法完全刪除該行(或者可能形成可能的解決方案),他們必須返回類似null。我從來沒有見過這種方法在實踐中被用來處理標題行,因爲它使閱讀變得很痛苦,並且閱讀往往比寫作更普遍。如果您正在處理一個表或者如果標題行只是許多格式不正確的行中的一行,它可能有一席之地。

您可以通過刪除數據加載中的第一行來進行一次過濾。 INSERT聲明中的WHERE子句可以做到這一點。你可以使用像sed這樣的工具來擺脫它。我已經看到兩種方法。在你採用哪種方法之間存在權衡,也不是處理標題行的真正方法。不幸的是,這兩種方法都需要時間並需要臨時重複數據。如果您確實需要另一個應用程序的標題行,則重複將是永久性的。

更新:

從蜂巢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"); 
+11

看起來您現在可以使用「SET skip.header.line.count = 1;」跳過標題行。欲瞭解更多信息,請參閱[https://issues.apache.org/jira/browse/HIVE-5795](https://issues.apache.org/jira/browse/HIVE-5795)上的補丁說明。 –

+0

感謝您的更新!目前,我並未與Hive合作,以便及時瞭解像這樣的更改。我已經發布了一個社區wiki,所以如果你已經測試了SET skip.header.line.count,我將不勝感激,如果你能解決我的問題(儘管在0.13.0版本以下的版本中有一段時間的解決辦法) 。 –

1

我不太確定它是否適用於ROW FORMAT serde'com.bizo.hive.serde.csv.CSVSerde',但我猜它應該與ROW FORMAT DELIMITED FIELDS TERMINATED BY','類似。
在你的情況下,第一行將被視爲正常行。但是第一個字段不能是INT,因此第一行的所有字段都將設置爲NULL。你只需要一箇中間步驟來解決它:

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

只有一個缺點是,你原來的csv文件將被修改。我希望它有幫助。 GL!

+0

正在使用CSVSerDe消除CSV文件中的雙引號。 –

1

我也爲此而苦苦掙扎,發現沒有辦法告訴配置單元跳過第一行,就像存在在Greenplum。所以最後我不得不從文件中刪除它。 例如「cat File.csv | grep -v RecordId> File_no_header。CSV」

1
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'); 
0

skip.header.line.count的作品,但如果你有一些外部工具訪問訪問這個表,它仍然會看到,沒有跳過這些行

8

當你從你的答案實際數據大牛,這是使用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') 

有了這個,你有過的分隔符,引號字符總量控制,轉義字符,空值處理和報頭處理

herehere

+0

來這裏尋找這個答案,因爲我使用AWS Athena,這需要我使用OpenCSVSerde。我有一段時間沒有碰過HIVE,但由於SerDe來自HIVE棧,所以很高興看到關於OpenCSVSerde的次要答案。謝謝@Nirmal –

+1

一個重要的注意事項 - 我在SerDe文檔中發現了這一點。 *限制* 此SerDe將所有列都視爲String類型。即使使用此SerDe創建包含非字符串列類型的 表,DESCRIBE TABLE輸出也會顯示字符串列類型。類型信息是從SerDe中檢索的 。要將列轉換爲 表中的所需類型,可以在表上創建一個視圖,將CAST轉換爲 所需的類型。 –

1

只需追加屬性在您的查詢和第一個標題或行int記錄將不會加載或將被跳過。

試試這個

tblproperties ("skip.header.line.count"="1"); 
+1

不是說這個解決方案也包含在頂級答案中:-) – Carpetsmoker