如何将Hive表导出为CSV文件?

70

我使用这个Hive查询将一个表导出到CSV文件中。

INSERT OVERWRITE DIRECTORY '/user/data/output/test' select column1, column2 from table1;

生成的文件'000000_0'没有逗号分隔符

这是生成CSV文件的正确方式吗?如果不是,请告诉我如何生成CSV文件?


另一个问题,当我将一个大的Hive表保存到HDFS上的几个块时,有时候发现它们的模式会变得不同,即列的类型可能会改变。如何防止这个问题的发生? - Song
17个回答

90

或者使用这个

hive -e 'select * from your_Table' | sed 's/[\t]/,/g'  > /home/yourfile.csv

您可以在SELECT之前指定属性set hive.cli.print.header=true,以确保标题与数据一起创建并复制到文件中。例如:
hive -e 'set hive.cli.print.header=true; select * from your_Table' | sed 's/[\t]/,/g'  > /home/yourfile.csv

如果你不想写入本地文件系统,可以使用 sed 命令的输出管道返回到 HDFS 中,使用 hadoop fs -put 命令。
另外,使用类似于 Cyberduck 的工具通过 SFTP 访问文件也很方便,或者你可以使用 scp 命令通过终端/命令提示符进行连接。

通过使用此命令,Hive 数据类型(如“double”)不会在 CSV 中传递。因此,当我读取 CSV 时,所有数据都被读取为字符串。 - Aman Mathur
1
在Hive的第3个版本中,Hive CLI被Beeline所取代,查询的输出结果略有不同,因为它包含了格式化。 - Arthur Lekane
我尝试将Hive查询导出到本地和HDFS文件,但是同一个文件无法从Spark会话中读取 - 标头未正确识别!! - Albin Chandy
虽然这种方法大多数情况下都有效,但如果查询结果值中有 '\t',它就会出错。我们该如何解决这个问题? - Jianwu Chen

55
如果您正在使用Hive 11或更高版本,则可以在INSERT语句中使用LOCAL关键字。
示例:
insert overwrite local directory '/home/carter/staging' row format delimited fields terminated by ',' select * from hugetable;

请注意这可能会创建多个文件,完成导出后您可能希望在客户端上将它们连接起来。

使用这种方法意味着您无需担心源表格的格式,可以基于任意SQL查询进行导出,并且可以选择自己的分隔符和输出格式。


谢谢,这个操作创建了一个包含多个CSV文件的文件夹。有没有办法将所有文件合并成一个文件?另外,有没有办法在CSV文件中包含标题(列名)? - mike
1
在导出后,您如何在客户端上连接它们? - user2205916
对我来说,这个命令生成了一堆以扩展名 .snappy 结尾的文件,看起来像是压缩格式。我不确定如何将它们解压缩。我知道如何使用命令 cat file1 file2 > file 在我的本地机器上合并文件。 - Ravi Chandra

43
那应该适合你的需求。
  • tab separated

    hive -e 'select * from some_table' > /home/yourfile.tsv
  • comma separated

    hive -e 'select * from some_table' | sed 's/[\t]/,/g' > /home/yourfile.csv

4
这将作为以制表符分隔的格式进行导出。 - Brett Bonner
正在运行:hive -e 'use <数据库或模式名称>; select * from <表名>;' > <CSV文件的绝对路径>/<CSV文件名>.csv - JGS
在大公司中,通常需要为此类作业分配一个队列名称,其中 -hiveconf 起到了作用,否则您将无法运行它。 - Li haonan
@Lihaonan,我该如何在查询中分配队列名称? - lboniotti

23

在生成报表后(就像您所做的那样),您不能为查询输出设置分隔符。

您可以将分隔符更改为逗号。

它带有默认的分隔符\001(不可见字符)。

hadoop fs -cat /user/data/output/test/* |tr "\01" "," >>outputwithcomma.csv

也可以查看这个链接


11
INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select * from table; 

是正确答案。

如果记录数非常大,根据生成的文件数量,下面的命令将只会给出部分结果。

hive -e 'select * from some_table' > /home/yourfile.csv

我该如何处理这个错误信息:用户 user_id 没有查询的权限 - sAguinaga
检查 Ranger 的策略以解决与 Hive 相关的权限错误。 - Petro

9
最近版本的Hive具备了这个功能。
INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' 
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY ',' 
select * from table;

通过这种方式,您可以选择自己的分隔符和文件名。 只要小心"覆盖",它将尝试从指定的文件夹中删除所有内容。


4
我使用简单的Linux shell管道和Perl将Hive生成的TSV输出转换为CSV格式。
hive -e "SELECT col1, col2, … FROM table_name" | perl -lpe 's/"/\\"/g; s/^|$/"/g; s/\t/","/g' > output_file.csv

我曾经在stackoverflow上从某人那里获取了更新的perl正则表达式。
结果将类似于常规csv: "col1","col2","col3"...等等

4
以下脚本应该适合您使用:
#!/bin/bash
hive -e "insert overwrite local directory '/LocalPath/'
row format delimited fields terminated by ','
select * from Mydatabase,Mytable limit 100"
cat /LocalPath/* > /LocalPath/table.csv

因为我有一个非常大的表格,所以我使用limit 100限制了数据的大小,但是你可以删除它来导出整个表格。


2

使用Hive仓库目录,您可以导出数据而不是Hive表。 首先,给出Hive仓库路径,然后是本地路径,您想存储.csv文件的位置。 该命令如下:

hadoop fs -cat /user/hdusr/warehouse/HiveDb/tableName/* > /users/hadoop/test/nilesh/sample.csv

2

这是在Hive的SQL中执行操作的更加简单的方式:

set hive.execution.engine=tez;
set hive.merge.tezfiles=true;
set hive.exec.compress.output=false;

INSERT OVERWRITE DIRECTORY '/tmp/job/'
ROW FORMAT DELIMITED
FIELDS TERMINATED by ','
NULL DEFINED AS ''
STORED AS TEXTFILE
SELECT * from table;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接