如何跳过 Hive 外部表中的 CSV 标头?

Posted

技术标签:

【中文标题】如何跳过 Hive 外部表中的 CSV 标头?【英文标题】:How to skip CSV header in Hive External Table? 【发布时间】:2013-03-23 00:46:43 【问题描述】:

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

谁能帮我跳过第一行或者我需要添加一个中间步骤吗?

【问题讨论】:

我自己刚开始玩 Hive,据我所知,SerDe 的工作只能逐行进行,因此如果没有一些中间体,这可能是不可能的。如果我能想到什么,我会在这里发布。我也对解决方案感兴趣。 【参考方案1】:

截至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");

对现有表使用ALTER TABLE

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

请注意,虽然它有效,但它也有其自身的问题。当生成多个输出文件时,即 reducer 大于 1,它会跳过每个文件的第一条记录,这可能不一定是所需的行为。

【讨论】:

看起来你现在可以使用“SET skip.header.line.count = 1;”跳过标题行。有关更多信息,请参阅https://issues.apache.org/jira/browse/HIVE-5795 的补丁说明。【参考方案2】:

虽然您从 Daniel 那里得到了答案,但可以使用 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。

【讨论】:

来到这里寻找这个答案,因为我使用的是 AWS Athena,这需要我使用 OpenCSVSerde。我有一段时间没有接触过 HIVE 的任何东西,但由于这个 SerDe 来自 HIVE 堆栈,很高兴看到这个关于 OpenCSVSerde 的次要答案。谢谢@Nirmal 一个重要提示 - 我在 SerDe 文档中发现了这一点。 限制 此 SerDe 将所有列都视为字符串类型。即使您使用此 SerDe 创建具有非字符串列类型的表,DESCRIBE TABLE 输出也会显示字符串列类型。从 SerDe 检索类型信息。要将表中的列转换为所需的类型,您可以在表上创建一个视图,将 CAST 转换为所需的类型。【参考方案3】:

只需在查询中附加下面的属性,记录的第一个标题或行将不会加载或将被跳过。

试试这个

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

【讨论】:

【参考方案4】:

skip.header.line.count 将跳过标题行。

但是,如果您有一些外部工具访问该表,它仍然会看到实际数据而不会跳过这些行

【讨论】:

【参考方案5】:
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');

【讨论】:

【参考方案6】:

我不太确定它是否适用于 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!

【讨论】:

CSVSerDe 用于消除 CSV 文件中的双引号。【参考方案7】:

仅适用于已经创建带有标题的表格的人。这是相同的alter命令。如果您已经拥有该表并希望在不删除和重新创建的情况下忽略第一行,这很有用。它还有助于人们熟悉 ALTER 作为 TBLPROPERTIES 的一个选项。

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

【讨论】:

【参考方案8】:

我也为此苦苦挣扎,发现无法告诉 hive 跳过第一行,例如有在格林普拉姆。所以最后我不得不从文件中删除它。 例如"cat File.csv | grep -v RecordId > File_no_header.csv"

【讨论】:

以上是关于如何跳过 Hive 外部表中的 CSV 标头?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 csv 文件中忽略带引号的换行符以创建 Hive 外部表?

如何在子查询中使用外部查询中的列从另一个表中获取结果?

Hive 外部表未从 CSV 源读取整个字符串

从 hive 外部表中的分区中删除列

Spark 不使用 Hive 分区外部表中的分区信息

如何将数据从 CSV 加载到 impala 的外部表中