【问题标题】:Hive INSERT OVERWRITE DIRECTORY command output is not separated by a delimiter. Why?Hive INSERT OVERWRITE DIRECTORY 命令输出没有用分隔符分隔。为什么?
【发布时间】:2013-05-09 10:37:01
【问题描述】:

我正在加载的文件由“”(空格)分隔。下面是文件。该文件位于 HDFS 中:-

001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

1> 我正在创建一个外部表并通过发出以下命令加载文件:-

CREATE EXTERNAL TABLE IF NOT EXISTS graph_edges (src_node_id STRING COMMENT 'Node ID of Source node', dest_node_id STRING COMMENT 'Node ID of Destination node') ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' STORED AS TEXTFILE LOCATION '/user/hadoop/input';

2> 在此之后,我只是通过发出以下命令将表插入到另一个文件中:-

INSERT OVERWRITE DIRECTORY '/user/hadoop/output' SELECT * FROM graph_edges;

3> 现在,当我对文件进行分类时,字段不会被任何分隔符分隔:-

hadoop dfs -cat /user/hadoop/output/000000_0

输出:-

001000
001000
002001
003002
004003
005004
006005
007006
008007
099007

有人可以帮帮我吗?为什么要删除分隔符以及如何分隔输出文件?

在 CREATE TABLE 命令中,我尝试了DELIMITED BY '\t',但随后我得到了不必要的 NULL 列。

非常感谢任何指针的帮助。我正在使用 Hive 0.9.0 版本。

【问题讨论】:

  • 你确定输出目录中没有分隔符吗?默认情况下,Hive 使用 '\1' 作为字段分隔符,因此您应该尝试 `hadoop dfs -cat "/user/hadoop/output/*" | tr '\001' ' '
  • 一定要从@garren 看到答案——当前版本的Hive 允许INSERT OVERWRITE DIRECTORY...ROW FORMATINSERT OVERWRITE DIRECTORY...STORED AS

标签: hadoop hive


【解决方案1】:

问题是 HIVE 不允许你指定输出分隔符 - https://issues.apache.org/jira/browse/HIVE-634

解决方案是为输出创建外部表(带分隔符规范)并插入覆盖表而不是目录。

--

假设您在 HDFS 中有 /user/hadoop/input/graph_edges.csv,

hive> create external table graph_edges (src string, dest string) 
    > row format delimited 
    > fields terminated by ' ' 
    > lines terminated by '\n' 
    > stored as textfile location '/user/hadoop/input';

hive> select * from graph_edges;
OK
001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

hive> create external table graph_out (src string, dest string) 
    > row format delimited 
    > fields terminated by ' ' 
    > lines terminated by '\n' 
    > stored as textfile location '/user/hadoop/output';

hive> insert into table graph_out select * from graph_edges;
hive> select * from graph_out;
OK
001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

[user@box] hadoop fs -get /user/hadoop/output/000000_0 .

如上返回,带有空格。

【讨论】:

  • 我创建了一个新的 non external 表,然后将数据从外部表插入到内部表到 HDFS 文件中。但还是一样的结果,根本没有分隔符。即使 Hive 不允许指定输出分隔符,它也必须用某个分隔符分隔输出。
  • 好的,假设你在HDFS中有/user/hadoop/input/graph_edges.csv,
  • 是的,graph_edges 文件在 HDFS 中。我将编辑我的问题以提供此详细信息。另外,请注意graph_edges 不是逗号分隔的文件,它是空格分隔的文件。
  • 这确实有效。非常感谢。所以我学到的一点是,在 Hive 中,为了保留格式/分隔符,应该始终将外部表写入另一个外部表,尽管在我看来我发现这个限制是一个错误。
  • 是的,有一个请求能够指定插入覆盖的格式。不客气!
【解决方案2】:

虽然该问题已有 2 年多的历史并且当时的最佳答案是正确的,但现在可以告诉 Hive 将分隔数据写入目录。

这里是一个使用传统的^A分隔符输出数据的例子:

INSERT OVERWRITE DIRECTORY '/output/data_delimited'
SELECT *
FROM data_schema.data_table

现在有了制表符分隔符:

INSERT OVERWRITE DIRECTORY '/output/data_delimited'
row format delimited 
FIELDS TERMINATED BY '\t'
SELECT *
FROM data_schema.data_table

【讨论】:

  • from here: “自定义分隔符仅支持 Hive 版本 0.11.0 到 1.1.0 中的本地写入 - 此错误已在版本 1.2.0 中修复(请参阅 HIVE-5672)”跨度>
【解决方案3】:

我认为使用 concat_ws 函数可以实现你的输出;

插入覆盖目录'/user/hadoop/output'选择 concat_ws(',', col1, col2) FROM graph_edges;

这里我选择了逗号作为列分隔符

【讨论】:

    【解决方案4】:

    我有一些不同的声音。

    确实,Hive 不支持自定义分隔符。

    但是当您使用INSERT OVERWRITE DIRECTORY 时,您的行中有分隔符。分隔符为'\1'

    您可以使用hadoop dfs -cat $file | head -1 | xxd 找到它或将文件从HDFS 获取到本地计算机并使用vim 打开它。在你的 vim 中会有一些像 '^A' 这样的字符,它是分隔符。

    回到问题,你可以用一个简单的方法来解决它。

    1. 依然使用INSERT OVERWRITE DIRECTORY '/user/hadoop/output'生成/user/hadoop/output

    2. 创建字段由'\1'分隔的外部表:

      create external table graph_out (src string, dest string) 
      row format delimited 
      fields terminated by '\1' 
      lines terminated by '\n' 
      stored as textfile location '/user/hadoop/output';
      

    【讨论】:

      【解决方案5】:

      写入目录时可以提供分隔符

      INSERT OVERWRITE DIRECTORY '/user/hadoop/output'
      ROW FORMAT DELIMITED
      FIELDS TERMINATED BY
      SELECT * FROM graph_edges;
      

      这应该适合你。

      【讨论】:

      • 我收到错误:失败:ParseException 行 2:0 无法识别 select 子句中“ROW”“FORMAT”“DELIMITED”附近的输入
      【解决方案6】:

      我遇到了这个问题,即 hive 查询结果的输出应该用管道分隔。 运行这个 sed 命令可以替换:^A to |

      sed 's#\x01#|#g' test.log > piped_test.log

      【讨论】:

        【解决方案7】:

        默认分隔符是“^A”。在python语言中是"\x01"

        当我想更改分隔符时,我使用 SQL 如下:

        SELECT col1, delimiter, col2, delimiter, col3, ..., 来自表

        那么,将delimiter+"^A"视为新的分隔符。

        【讨论】:

          【解决方案8】:

          我怀疑 hive 实际上正在编写一个 contol-A 作为分隔符,但是当你在屏幕上做一只猫时,它并没有出现在你的眼前。

          如果您只想看一点文件,请尝试在 vi 中调出文件或 head 文件,然后 vi 显示结果:

          hadoop dfs -cat /user/hadoop/output/000000_0 |头> my_local_file.txt

          vi my_local_file.txt

          您应该能够看到其中的 ^A 字符。

          【讨论】:

            【解决方案9】:

            我想这将是一个更好的解决方案,尽管它是一种实现方式。

            INSERT OVERWRITE DIRECTORY '/user/hadoop/output' SELECT src_node_id,' ',dest_node_id FROM graph_edges;

            【讨论】:

              【解决方案10】:

              您可以使用此参数“以'|'终止的行格式分隔字段”例如在您的情况下应该是

              INSERT OVERWRITE DIRECTORY '/user/hadoop/output' 行格式分隔字段以 '|' 终止SELECT * FROM graph_edges;

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-11-29
                • 1970-01-01
                • 1970-01-01
                • 2015-12-23
                • 2018-07-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多