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

时间:2013-06-13 12:04:53

标签: csv hive

我使用此Hive查询将表导出为CSV文件。

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

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

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

16 个答案:

答案 0 :(得分:52)

或使用此

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

您还可以在set hive.cli.print.header=true之前指定属性SELECT,以确保创建标题以及数据并将其复制到文件中。 例如:

hive -e 'set hive.cli.print.header=true; select * from your_Table' | sed 's/[\t]/,/g'  > /home/yourfile.csv

如果您不想写入本地文件系统,请使用sed命令将HDFS命令的输出反馈回hadoop fs -put

答案 1 :(得分:47)

如果您使用的是Hive 11或更高版本,则可以将INSERT语句与LOCAL关键字一起使用。

示例:

insert overwrite local directory '/home/carter/staging' row format delimited fields terminated by ',' select * from hugetable;

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

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

答案 2 :(得分:34)

这应该对你有用

  • 标签分隔

    hive -e 'select * from some_table' > /home/yourfile.tsv
  • 以逗号分隔

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

答案 3 :(得分:21)

生成报告后,您无法为查询输出设置分隔符(正如您所做的那样)。

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

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

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

check this also

答案 4 :(得分:8)

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

答案 5 :(得分:6)

最新版本的hive附带此功能。

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

这样您就可以选择自己的分隔符和文件名。 只需注意“ OVERWRITE ”,它就会尝试删除上述文件夹中的所有内容。

答案 6 :(得分: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" ...等等

答案 7 :(得分: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来限制数据的大小,因为我有一个庞大的表,但您可以将其删除以导出整个表。

答案 8 :(得分:2)

在这里使用Hive仓库目录,您可以导出数据而不是Hive表。 首先给出hive仓库路径,然后在你想要存储.csv文件的本地路径之后 这个命令如下: -

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

答案 9 :(得分:1)

我有类似的问题,这就是我能够解决的问题。

步骤1 - 将数据从hive表加载到另一个表中,如下所示

  

DROP TABLE IF EXISTS TestHiveTableCSV;   CREATE TABLE TestHiveTableCSV行格式删除字段由','终止线路终止于' \ n'如   SELECT列表FROM TestHiveTable;

步骤2 - 将hb仓库中的blob复制到具有适当扩展名的新位置

  

Start-AzureStorageBlobCopy -DestContext $destContext   -SrcContainer" Source Container" -SrcBlob "hive/warehouse/TestHiveTableCSV/000000_0"   -DestContainer" Destination Container" `   -DestBlob" CSV / TestHiveTable.csv"

希望这有帮助!

最诚挚的问候, Dattatrey Sindol(达塔) http://dattatreysindol.com

答案 10 :(得分:1)

有一些方法可以更改默认分隔符,如其他答案所示。

还有一些方法可以使用一些bash脚本将原始输出转换为csv。但是要考虑3个分隔符,而不仅仅是\ 001。当你的hive表有maps时,事情会变得复杂一些。

我写了一个bash脚本,它可以处理来自hive的所有3个默认分隔符(\ 001 \ 002和\ 003)并输出一个csv。脚本和更多信息在这里:

  

Hive默认分隔符为CSV

     

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

的更多解释

答案 11 :(得分:1)

如果要从Windows进行操作,则可以使用Python脚本hivehoney将表数据提取到本地CSV文件中。

它将:

  • 登录到堡垒主机。
  • 普朗。
  • 起义。
  • 直线(带有您的查询)。
  • 保存 从beeline回显到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

答案 12 :(得分:1)

问题解决方案很好,但是我都发现了一些问题:

  • 正如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

答案 13 :(得分:0)

下面是我用来将Hive表数据作为带有标题的单个命名CSV文件导出到HDFS的端到端解决方案。
(不幸的是,无法使用一个HQL语句)
它由几个命令组成,但我认为它非常直观,并且不依赖于Hive表的内部表示,该表示可能会不时发生变化。
如果要将数据导出到与HDFS相对的本地文件系统中,请用“本地目录”替换“目录”。

# 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

答案 14 :(得分:0)

尝试

hive --outputformat==csv2 -e "select * from YOUR_TABLE";

这对我有用

我的蜂巢版本是“ Hive 3.1.0.3.1.0.0-78”

答案 15 :(得分:0)

这是在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;