この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
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
にパイプで戻します。
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
Hiveの最新バージョンにはこの機能が付属しています。
INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
select * from table;
このようにして、独自の区切り文字とファイル名を選択できます。 「OVERWRITE」に注意してください。指定されたフォルダーからすべてを削除しようとします。
次のスクリプトが動作するはずです。
#!/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
を使用してデータのサイズを制限しましたが、削除してテーブル全体をエクスポートできます。
単純なLinuxシェルパイピング+ 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"
...など
ここでは、Hiveウェアハウスディレクトリを使用して、Hiveテーブルの代わりにデータをエクスポートできます。最初にHiveウェアハウスパスを指定し、.csvファイルを保存するローカルパスの後にこのコマンドを以下に示します。
hadoop fs -cat /user/hdusr/warehouse/HiveDb/tableName/* > /users/hadoop/test/nilesh/sample.csv
他の回答に示されているように、デフォルトの区切り文字を変更する方法があります。
また、bashスクリプトを使用して生の出力をcsvに変換する方法もあります。ただし、考慮すべき区切り文字は3つあり、\ 001だけではありません。 Hiveテーブルに maps があると、事態は少し複雑になります。
Hiveの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
the Gist の詳細説明
私は同様の問題を抱えていましたが、これは私がそれを解決する方法でした。
ステップ1-次のように、Hiveテーブルから別のテーブルにデータをロードしました
TestHiveTableCSVが存在する場合はドロップテーブル。 CREATE TABLE TestHiveTableCSV行フォーマット '、'で終了するフィールドの区切り、 '\ n'で終了する行、SELECT列リストからTestHiveTable。
ステップ2-BlobをHiveウェアハウスから適切な拡張子を持つ新しい場所にコピーしました
Start-AzureStorageBlobCopy
-DestContext $destContext
-SrcContainer "Source Container"-SrcBlob "Hive/warehouse/TestHiveTableCSV/000000_0"
-DestContainer "Destination Container" `-DestBlob" CSV/TestHiveTable.csv "
お役に立てれば!
よろしく、Dattatrey Sindol(Datta) http://dattatreysindol.com
問題の解決策は問題ありませんが、両方でいくつかの問題が見つかりました。
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
Windowsから実行する場合は、Python script hivehoney を使用して、テーブルデータをローカルCSVファイルに抽出できます。
そうなる:
次のように実行します。
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
以下は、Hiveテーブルデータをヘッダー付きの単一の名前付きCSVファイルとしてHDFSにエクスポートするために使用するエンドツーエンドソリューションです。
(1つの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