Hive外部表跳过第一行

时间:2013-04-01 21:13:55

标签: hive cloudera

我正在使用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"

任何人都可以帮我解决如何跳过第一行或者我是否需要添加中间步骤?

8 个答案:

答案 0 :(得分:68)

数据中的标题行是Hive中永久性的头痛问题。如果没有修改Hive源,我相信没有中间步骤就无法逃脱。 (编辑:这不再是真的,请参阅下面的更新)

不幸的是,这回答了你的问题。我将为完整性的中间步骤提出一些想法。

如果您愿意在每个触及表格的查询中过滤掉标题行,则可以在数据加载中没有额外步骤的情况下离开。不幸的是,这增加了其他地方的额外设置。当标题行违反您的模式时,您将不得不变得聪明/凌乱。如果你采用这种方法,你可以考虑编写一个自定义的SerDe,使这行更容易过滤。不幸的是,SerDe不能完全删除该行(或者可能形成可能的解决方案),它们必须返回null之类的内容。我从来没有在实践中看到这种方法来处理标题行,因为它使阅读变得痛苦,阅读往往比写作更常见。如果您正在处理一个表,或者标题行只是许多格式错误的行中的一行,那么它可能有一个位置。

您可以使用删除数据加载中第一行的变体进行一次此过滤。 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");

答案 1 :(得分:11)

虽然你得到了丹尼尔的答案,但可以使用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

答案 2 :(得分:7)

只需在您的查询中追加属性下方,并且第一个标题或行内容将不会加载记录或将被跳过。

试试这个

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

答案 3 :(得分:2)

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

答案 4 :(得分:2)

skip.header.line.count有效但如果您有一些外部工具访问此表,它仍然会看到实际数据而不跳过这些行

答案 5 :(得分: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!

答案 6 :(得分:1)

仅适用于已经使用表头创建表的用户。这是相同的alter命令。如果您已经有了该表并希望在不删除和重新创建的情况下忽略第一行,这将很有用。它还可以帮助人们熟悉ALTER,并将其作为TBLPROPERTIES的选择。

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

答案 7 :(得分:0)

我也在努力解决这个问题,并且没有办法告诉蜂巢跳过第一行,例如在Greenplum。所以最后我不得不从文件中删除它。 例如“cat File.csv | grep -v RecordId&gt; File_no_header.csv”