如何将 Hive 表导出为 CSV 文件?
Posted
技术标签:
【中文标题】如何将 Hive 表导出为 CSV 文件?【英文标题】:How to export a Hive table into a CSV file? 【发布时间】:2013-06-09 19:31:22 【问题描述】:我使用此 Hive 查询将表导出到 CSV 文件中。
INSERT OVERWRITE DIRECTORY '/user/data/output/test' select column1, column2 from table1;
生成的文件“000000_0”没有逗号分隔符
这是生成 CSV 文件的正确方法吗?如果没有,请告诉我如何生成 CSV 文件?
【问题讨论】:
【参考方案1】:这是在 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;
【讨论】:
【参考方案2】:试试
hive --outputformat==csv2 -e "select * from YOUR_TABLE";
这对我有用
我的 hive 版本是“Hive 3.1.0.3.1.0.0-78”
【讨论】:
【参考方案3】:或者使用这个
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
如果您不想写入本地文件系统,请使用hadoop fs -put
命令将sed
命令的输出传送回HDFS
。
使用Cyberduck 之类的方式将文件通过 SFTP 传输到您的文件可能也很方便,或者您可以使用 scp
通过终端/命令提示符进行连接。
【讨论】:
通过使用此命令,'double' 等 hive 数据类型不会在 CSV 中结转。因此,当我阅读 CSV 时,所有内容都被读取为字符串。 在hive cli被beeline替换的hive版本3中,查询的输出略有不同,因为它包含格式 我尝试将其导出以将 hive 查询导出到本地和 hdfs 文件,但无法从 spark 会话中读取相同的文件 - 标头未正确识别!【参考方案4】:下面是我用来将 Hive 表数据导出到 HDFS 作为带有标题的单个命名 CSV 文件的端到端解决方案。 (不幸的是,不可能只使用一个 HQL 语句) 它由几个命令组成,但我认为它非常直观,并且它不依赖于 Hive 表的内部表示,它可能会不时改变。 如果要将数据导出到本地文件系统而不是 HDFS,请将“DIRECTORY”替换为“LOCAL DIRECTORY”。
# cleanup the existing target HDFS directory, if it exists
sudo -u hdfs hdfs dfs -rm -f -r /tmp/data/my_exported_table_name/*
# export the data using Beeline CLI (it will create a data file with a surrogate name in the target HDFS directory)
beeline -u jdbc:hive2://my_hostname:10000 -n hive -e "INSERT OVERWRITE DIRECTORY '/tmp/data/my_exported_table_name' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' SELECT * FROM my_exported_table_name"
# set the owner of the target HDFS directory to whatever UID you'll be using to run the subsequent commands (root in this case)
sudo -u hdfs hdfs dfs -chown -R root:hdfs /tmp/data/my_exported_table_name
# write the CSV header record to a separate file (make sure that its name is higher in the sort order than for the data file in the target HDFS directory)
# also, obviously, make sure that the number and the order of fields is the same as in the data file
echo 'field_name_1,field_name_2,field_name_3,field_name_4,field_name_5' | hadoop fs -put - /tmp/data/my_exported_table_name/.header.csv
# concatenate all (2) files in the target HDFS directory into the final CSV data file with a header
# (this is where the sort order of the file names is important)
hadoop fs -cat /tmp/data/my_exported_table_name/* | hadoop fs -put - /tmp/data/my_exported_table_name/my_exported_table_name.csv
# give the permissions for the exported data to other users as necessary
sudo -u hdfs hdfs dfs -chmod -R 777 /tmp/data/hive_extr/drivers
【讨论】:
【参考方案5】:问题解决方案很好,但我发现两者都有一些问题:
正如 Carter Shanklin 所说,使用此命令,我们将在指定的路径中获得一个带有查询结果的 csv 文件:
insert overwrite local directory '/home/carter/staging' row format delimited fields terminated by ',' select * from hugetable;
这个解决方案的问题是获得的 csv 没有标题,并且会创建一个不是 CSV 的文件(所以我们必须重命名它)。
正如user1922900所说,使用以下命令我们将获得一个CSV文件,其中包含指定文件中的查询结果和标题:
hive -e 'select * from some_table' | sed 's/[\t]/,/g' > /home/yourfile.csv
使用此解决方案,我们将获得一个包含查询结果行的 CSV 文件,但这些行之间也包含日志消息。作为这个问题的解决方案,我尝试了this,但没有结果。
所以,为了解决所有这些问题,我创建了一个脚本来执行查询列表,创建一个文件夹(带有时间戳)来存储结果,重命名获得的文件,删除不需要的文件,并添加相应的标题。
#!/bin/sh
QUERIES=("select * from table1" "select * from table2")
IFS=""
directoryname=$(echo "ScriptResults$timestamp")
mkdir $directoryname
counter=1
for query in $QUERIES[*]
do
tablename="query"$counter
hive -S -e "INSERT OVERWRITE LOCAL DIRECTORY '/data/2/DOMAIN_USERS/SANUK/users/$USER/$tablename' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' $query ;"
hive -S -e "set hive.cli.print.header=true; $query limit 1" | head -1 | sed 's/[\t]/,/g' >> /data/2/DOMAIN_USERS/SANUK/users/$USER/$tablename/header.csv
mv $tablename/000000_0 $tablename/$tablename.csv
cat $tablename/$tablename.csv >> $tablename/header.csv.
rm $tablename/$tablename.csv
mv $tablename/header.csv $tablename/$tablename.csv
mv $tablename/$tablename.csv $directoryname
counter=$((counter+1))
rm -rf $tablename/
done
【讨论】:
【参考方案6】:如果您是从 Windows 执行此操作,您可以使用 Python 脚本 hivehoney 将表数据提取到本地 CSV 文件。
它会:
登录堡垒主机。 pbrun。 启动。 直线(与您的查询)。 保存 从直线回显到 Windows 上的文件。这样执行:
set PROXY_HOST=your_bastion_host
set SERVICE_USER=you_func_user
set LINUX_USER=your_SOID
set LINUX_PWD=your_pwd
python hh.py --query_file=query.sql
【讨论】:
【参考方案7】:以下脚本应该适合您:
#!/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
来限制数据的大小,因为我有一个很大的表,但是你可以删除它来导出整个表。
【讨论】:
【参考方案8】:在这里使用 Hive 仓库目录,您可以导出数据而不是 Hive 表。 首先给出 hive 仓库路径,然后是要存储 .csv 文件的本地路径 对于此命令如下:-
hadoop fs -cat /user/hdusr/warehouse/HiveDb/tableName/* > /users/hadoop/test/nilesh/sample.csv
【讨论】:
【参考方案9】:这应该适合你
制表符分隔
hive -e 'select * from some_table' > /home/yourfile.tsv
逗号分隔
hive -e 'select * from some_table' | sed 's/[\t]/,/g' > /home/yourfile.csv
【讨论】:
这将导出为制表符分隔 它正在工作:hive -e 'use-hiveconf
发挥作用,否则您无法运行它。
@Lihaonan,我如何在查询中分配队列名?【参考方案10】:
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 user_id does not have privileges for QUERY
?
检查 Ranger 的政策是否存在 hive 权限错误【参考方案11】:
如果您使用的是 Hive 11 或更高版本,则可以使用带有 LOCAL
关键字的 INSERT
语句。
例子:
insert overwrite local directory '/home/carter/staging' row format delimited fields terminated by ',' select * from hugetable;
请注意,这可能会创建多个文件,您可能希望在完成导出后在客户端将它们连接起来。
使用这种方式意味着您无需担心源表的格式,可以根据任意 SQL 查询导出,并且可以选择自己的分隔符和输出格式。
【讨论】:
谢谢,这个创建的文件夹包含多个 csv 文件。有没有办法把所有东西都放在一个文件中?还有是否在 csv 文件中包含标题(列名)? 导出后如何在客户端连接它们? 对我来说,这个命令产生了一堆以扩展名 .snappy 结尾的文件,看起来像是一种压缩格式。我不确定如何转换解压缩它们。我知道如何在本地机器上使用命令cat file1 file2 > file
在本地合并文件。【参考方案12】:
最近版本的 hive 带有此功能。
INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
select * from table;
这样您可以选择自己的分隔符和文件名。 请注意“OVERWRITE”,它会尝试从提到的文件夹中删除所有内容。
【讨论】:
【参考方案13】:我使用简单的 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
(前段时间我从 *** 中的某个人那里得到了更新的 perl 正则表达式)
结果会像普通的 csv:
"col1","col2","col3"
...等等
【讨论】:
【参考方案14】:有一些方法可以更改默认分隔符,如其他答案所示。
还有一些方法可以使用一些 bash 脚本将原始输出转换为 csv。不过,有 3 个分隔符需要考虑,而不仅仅是 \001。当您的 hive 表有 maps 时,事情会变得有点复杂。
我编写了一个 bash 脚本,它可以处理来自 hive 的所有 3 个默认分隔符(\001 \002 和 \003)并输出一个 csv。脚本和更多信息在这里:
CSV 的 Hive 默认分隔符
Hive 的默认分隔符是
Row Delimiter => Control-A ('\001') Collection Item Delimiter => Control-B ('\002') Map Key Delimiter => Control-C ('\003')
导出表格时有一些方法可以更改这些分隔符,但是 有时您可能仍然需要将其转换为 csv。
这是一个可以处理数据库导出的快速 bash 脚本 在多个文件中分段并具有默认分隔符。它会 输出单个 CSV 文件。
假设段都具有命名约定 000*_0
INDIRECTORY="path/to/input/directory" for f in $INDIRECTORY/000*_0; do echo "Processing $f file.."; cat -v $f | LC_ALL=C sed -e "s/^/\"/g" | LC_ALL=C sed -e "s/\^A/\",\"/g" | LC_ALL=C sed -e "s/\^C\^B/\"\":\"\"\"\",\"\"/g" | LC_ALL=C sed -e "s/\^B/\"\",\"\"/g" | LC_ALL=C sed -e "s/\^C/\"\":\"\"/g" | LC_ALL=C sed -e "s/$/\"/g" > $f-temp done echo "you,can,echo,your,header,here,if,you,like" > $INDIRECTORY/final_output.csv cat $INDIRECTORY/*-temp >> $INDIRECTORY/final_output.csv rm $INDIRECTORY/*-temp
更多解释the gist
【讨论】:
【参考方案15】:我遇到了类似的问题,这就是我能够解决的方法。
第 1 步 - 将 hive 表中的数据加载到另一个表中,如下所示
如果存在则删除表 TestHiveTableCSV; CREATE TABLE TestHiveTableCSV 行格式分隔的字段以 ',' 终止的行为 '\n' AS 从 TestHiveTable 中选择列列表;
第 2 步 - 将 blob 从 hive 仓库复制到具有适当扩展名的新位置
开始-AzureStorageBlobCopy
-DestContext $destContext
-SrcContainer“源容器”-SrcBlob "hive/warehouse/TestHiveTableCSV/000000_0"
-DestContainer“目标容器”` -DestBlob "CSV/TestHiveTable.csv"
希望这会有所帮助!
最好的问候, Dattatrey Sindol (达塔) http://dattatreysindol.com
【讨论】:
【参考方案16】:在生成报告后(如您所做的那样),您不能为查询输出设置分隔符。
您可以将分隔符更改为逗号。
它带有默认分隔符\001
(不可见字符)。
hadoop fs -cat /user/data/output/test/* |tr "\01" "," >>outputwithcomma.csv
check this also
【讨论】:
以上是关于如何将 Hive 表导出为 CSV 文件?的主要内容,如果未能解决你的问题,请参考以下文章