programing

Hive 테이블을 CSV 파일로 내보내는 방법은 무엇입니까?

yoursource 2021. 1. 16. 10:50
반응형

Hive 테이블을 CSV 파일로 내보내는 방법은 무엇입니까?


이 Hive 쿼리를 사용하여 테이블을 CSV 파일로 내보냈습니다.

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

생성 된 '000000_0'파일에 쉼표 구분 기호가 없습니다.

이것이 CSV 파일을 생성하는 올바른 방법입니까? 그렇지 않은 경우 CSV 파일을 어떻게 생성 할 수 있습니까?


또는 이것을 사용하십시오

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.


Hive 11 이상을 사용하는 INSERT경우 LOCAL키워드 와 함께 문을 사용할 수 있습니다 .

예:

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

이렇게하면 여러 파일이 생성 될 수 있으며 내보내기가 완료된 후 클라이언트 측에서 파일을 연결할 수 있습니다.

이 접근 방식을 사용하면 소스 테이블의 형식에 대해 걱정할 필요가 없으며 임의의 SQL 쿼리를 기반으로 내보낼 수 있으며 고유 한 구분 기호와 출력 형식을 선택할 수 있습니다.


그것은 당신을 위해 작동합니다

  • 탭 분리

    hive -e 'select * from some_table' > /home/yourfile.tsv
  • 쉼표로 구분

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

보고서를 생성 한 후에는 쿼리 출력에 대한 구분 기호를 사용할 수 없습니다.

구분 기호를 쉼표로 변경할 수 있습니다.

기본 구분 기호 \001(표시되지 않는 문자) 와 함께 제공됩니다 .

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

이것도 확인


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

최신 버전의 하이브에는이 기능이 제공됩니다.

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

이렇게하면 고유 한 구분 기호와 파일 이름을 선택할 수 있습니다. " 덮어 쓰기 "에 주의하십시오 . 언급 된 폴더에서 모든 것을 삭제하려고합니다.


간단한 리눅스 쉘 파이핑 + 펄을 사용하여 하이브 생성 출력을 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"... 등등


다음 스크립트가 작동합니다.

#!/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내가 큰 테이블을 가지고 있기 때문에 데이터의 크기를 제한하는,하지만 당신은 전체 테이블을 내보낼 삭제할 수 있습니다.


여기서 Hive웨어 하우스 디렉토리를 사용하여 Hive 테이블 대신 데이터를 내보낼 수 있습니다. 먼저 하이브웨어 하우스 경로를 제공하고 .csv 파일을 저장할 로컬 경로 뒤에이 명령은 다음과 같습니다.

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

나는 비슷한 문제가 있었고 이것이 내가 그것을 해결할 수 있었던 방법입니다.

1 단계-다음과 같이 하이브 테이블의 데이터를 다른 테이블에로드했습니다.

TestHiveTableCSV가있는 경우 테이블 삭제; Create TABLE TestHiveTableCSV ROW FORMAT DELIMITED FIELDS TERMINATED BY ','LINES TERMINATED BY '\ n'AS SELECT Column List from TestHiveTable;

2 단계-적절한 확장을 사용하여 Blob을 하이브웨어 하우스에서 새 위치로 복사했습니다.

Start-AzureStorageBlobCopy -DestContext $destContext-SrcContainer "소스 컨테이너" -SrcBlob "hive/warehouse/TestHiveTableCSV/000000_0"-DestContainer "대상 컨테이너"`-DestBlob "CSV / TestHiveTable.csv"

도움이 되었기를 바랍니다!

감사합니다, Dattatrey Sindol (Datta) http://dattatreysindol.com


다른 답변에서 볼 수 있듯이 기본 구분 기호를 변경하는 방법이 있습니다.

일부 bash 스크립팅을 사용하여 원시 출력을 csv로 변환하는 방법도 있습니다. 하지만 고려해야 할 구분 기호는 \ 001뿐 아니라 3 가지입니다. 하이브 테이블에 이 있으면 상황이 좀 더 복잡해집니다 .

하이브에서 3 개의 기본 구분 기호 (\ 001 \ 002 및 \ 003)를 모두 처리하고 csv를 출력 할 수있는 bash 스크립트를 작성했습니다. 스크립트 및 추가 정보는 다음과 같습니다.

Hive 기본 구분 기호를 CSV로

Hive의 기본 구분 기호는 다음과 같습니다.

Row Delimiter => Control-A ('\001')
Collection Item Delimiter => Control-B ('\002')
Map Key Delimiter => Control-C ('\003')

테이블을 내보낼 때 이러한 구분 기호를 변경하는 방법이 있지만 때로는 이것을 csv로 변환해야 할 필요가있을 수 있습니다.

다음은 여러 파일로 분할되고 기본 구분 기호가있는 DB 내보내기를 처리 할 수있는 빠른 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

More explanation on the gist


In case you are doing it from Windows you can use Python script hivehoney to extract table data to local CSV file.

It will:

  • Login to bastion host.
  • pbrun.
  • kinit.
  • beeline (with your query).
  • Save echo from beeline to a file on Windows.

Execute it like this:

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

The problem solutions are fine but I found some problems in both:

  • As Carter Shanklin said, with this command we will obtain a csv file with the results of the query in the path specified:

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

    The problem with this solution is that the csv obtained won´t have headers and will create a file that is not a CSV (so we have to rename it).

  • As user1922900 said, with the following command we will obtain a CSV files with the results of the query in the specified file and with headers:

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

    With this solution we will get a CSV file with the result rows of our query, but with log messages between these rows too. As a solution of this problem I tried this, but without results.

So, to solve all these issues I created a script that execute a list of queries, create a folder (with a timestamp) where it stores the results, rename the files obtained, remove the unnecesay files and it also add the respective headers.

 #!/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

Below is the end-to-end solution that I use to export Hive table data to HDFS as a single named CSV file with a header.
(it is unfortunate that it's not possible to do with one HQL statement)
It consists of several commands, but it's quite intuitive, I think, and it does not rely on the internal representation of Hive tables, which may change from time to time.
Replace "DIRECTORY" with "LOCAL DIRECTORY" if you want to export the data to a local filesystem versus 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

ReferenceURL : https://stackoverflow.com/questions/17086642/how-to-export-a-hive-table-into-a-csv-file

반응형