Wie gebe ich die Ergebnisse einer HiveQL-Abfrage an CSV aus?

79

Wir möchten die Ergebnisse einer Hive-Abfrage in eine CSV-Datei einfügen. Ich dachte, der Befehl sollte so aussehen:

insert overwrite directory '/home/output.csv' select books from table;

Wenn ich es ausführe, heißt es, dass es erfolgreich abgeschlossen wurde, aber ich kann die Datei nie finden. Wie finde ich diese Datei oder sollte ich die Daten auf andere Weise extrahieren?

AAA
quelle

Antworten:

145

Obwohl es möglich ist INSERT OVERWRITE, Daten aus Hive abzurufen, ist dies möglicherweise nicht die beste Methode für Ihren speziellen Fall. Lassen Sie mich zuerst erklären, was INSERT OVERWRITEfunktioniert, und dann die Methode beschreiben, mit der ich tsv-Dateien aus Hive-Tabellen abrufe.

Gemäß dem Handbuch speichert Ihre Abfrage die Daten in einem Verzeichnis in HDFS. Das Format wird nicht csv sein.

In das Dateisystem geschriebene Daten werden als Text mit durch ^ A getrennten Spalten und durch Zeilenumbrüche getrennten Zeilen serialisiert. Wenn eine der Spalten nicht vom primitiven Typ ist, werden diese Spalten in das JSON-Format serialisiert.

Durch eine geringfügige Änderung (Hinzufügen des LOCALSchlüsselworts) werden die Daten in einem lokalen Verzeichnis gespeichert.

INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' select books from table;

Wenn ich eine ähnliche Abfrage ausführe, sieht die Ausgabe folgendermaßen aus.

[lvermeer@hadoop temp]$ ll
total 4
-rwxr-xr-x 1 lvermeer users 811 Aug  9 09:21 000000_0
[lvermeer@hadoop temp]$ head 000000_0 
"row1""col1"1234"col3"1234FALSE
"row2""col1"5678"col3"5678TRUE

Persönlich führe ich meine Abfrage normalerweise direkt über Hive in der Befehlszeile für diese Art von Dingen aus und leite sie wie folgt in die lokale Datei:

hive -e 'select books from table' > /home/lvermeer/temp.tsv

Das gibt mir eine durch Tabulatoren getrennte Datei, die ich verwenden kann. Hoffe das ist auch für dich nützlich.

Basierend auf diesem Patch-3682 vermute ich, dass bei Verwendung von Hive 0.11 eine bessere Lösung verfügbar ist, kann dies jedoch nicht selbst testen. Die neue Syntax sollte Folgendes ermöglichen.

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

Hoffentlich hilft das.

Lukas Vermeer
quelle
2
kennen Sie einen Performance - Unterschied zwischen dem Einsatz überschreiben lokale und Rohrleitungen, bei denen Volumen angenähert kann es ein Problem werden, auch garantiert kochend Sie eine Datei erhalten werden, wie der andere Ansatz uns ein Verzeichnis gibt , die möglicherweise müssen wir danach verschmelzen
fd8s0
Ist es möglich, die Daten in HDFS als Sequenzdateiformat zu exportieren?
Nageswaran
1
Ich habe die Lösung (Patch-3682) ausprobiert und sie hat bei mir gut funktioniert - außer dass die Ausgabedatei aus irgendeinem Grund keine Header enthielt. Beachten Sie, dass ich hive.cli.print.header = true gesetzt habe; in meinem .hiverc. Für das, was es wert ist, wurden die Header stattdessen auf das Terminal gedruckt (was offensichtlich nicht das ist, was ich wollte).
Peter Cogan
@ lukas-vermeer, wenn Sie die Tabelle mit der Methode "INSERT OVERWRITE" erstellen, gehen die Header-Informationen verloren. Gibt es eine Möglichkeit, die Header-Informationen abzurufen?
ML_Passion
Hallo Lukas, wie hast du deine Shell im Hadoop-Dateisystem zum Laufen gebracht?
Notilas
22

Wenn Sie eine CSV-Datei möchten, können Sie die Lösungen von Lukas wie folgt ändern (vorausgesetzt, Sie befinden sich auf einer Linux-Box):

hive -e 'select books from table' | sed 's/[[:space:]]\+/,/g' > /home/lvermeer/temp.csv
David Kjerrumgaard
quelle
4
Danke dafür. Ich benutze eine Variation, aber sie funktioniert sehr gut. Bitte beachten Sie, dass dies durch Kommas getrennt ausgegeben wird, nicht unbedingt das, was manche Leute als CSV betrachten. CSV hat normalerweise eine Formatierung, um Daten mit Kommas zu verarbeiten (z. B. Daten mit doppelten Anführungszeichen umschließen und doppelte doppelte Anführungszeichen für Daten mit doppelten Anführungszeichen). Erwähnenswert ist, dass durch Hinzufügen des Parameters "--hiveconf hive.cli.print.header = True" auch Ihre Header in der Ausgabe angezeigt werden.
Juli
Dies ist die sauberste Lösung
Dutta
1
Dies schlug für mich beispielsweise bei einer Datums- / Uhrzeitzeichenfolge fehl, die ein Leerzeichen zwischen Datum und Uhrzeit enthielt.
Williaster
@williaster sed 's / \ t \ + /, / g' dies sollte bei diesem Problem helfen.
Sudhakar Chavan
Dies würde nicht funktionieren, wenn der tsv Text enthält, der Kommas enthält. (weil nicht
zitierte
4

Sie sollten die Anweisung CREATE TABLE AS SELECT (CTAS) verwenden, um ein Verzeichnis in HDFS mit den Dateien zu erstellen, die die Ergebnisse der Abfrage enthalten. Danach müssen Sie diese Dateien von HDFS auf Ihre normale Festplatte exportieren und zu einer einzigen Datei zusammenführen.

Möglicherweise müssen Sie auch einige Tricks ausführen, um die Dateien von '\ 001' - getrennt in CSV - zu konvertieren. Sie können eine benutzerdefinierte CSV-SerDe verwenden oder die extrahierte Datei nachbearbeiten.

Olaf
quelle
Dieser Ansatz ist am besten geeignet, wenn die Ausgabe in einem nachfolgenden Oozie-Pipeline-Schritt verwendet werden soll.
Cerd
4

Sie können verwenden INSERT... DIRECTORY..., wie in diesem Beispiel:

INSERT OVERWRITE LOCAL DIRECTORY '/tmp/ca_employees'
SELECT name, salary, address
FROM employees
WHERE se.state = 'CA';

OVERWRITEund LOCALhaben die gleichen Interpretationen wie zuvor und Pfade werden nach den üblichen Regeln interpretiert. /tmp/ca_employeesAbhängig von der Anzahl der aufgerufenen Reduzierer werden eine oder mehrere Dateien beschrieben .

Bigmaker
quelle
3

Wenn Sie HUE verwenden, ist dies ebenfalls ziemlich einfach. Gehen Sie einfach zum Hive-Editor in HUE, führen Sie Ihre Hive-Abfrage aus und speichern Sie die Ergebnisdatei lokal als XLS oder CSV, oder Sie können die Ergebnisdatei in HDFS speichern.

Strahl
quelle
3

Ich suchte nach einer ähnlichen Lösung, aber die hier genannten würden nicht funktionieren. Meine Daten enthielten alle Variationen von Leerzeichen (Leerzeichen, Zeilenumbrüche, Tabulatoren) und Kommas.

Um die Sicherheit der Spaltendaten tsv zu gewährleisten, habe ich alle \ t Zeichen in den Spaltendaten durch ein Leerzeichen ersetzt und Python-Code in der Befehlszeile ausgeführt, um eine CSV-Datei zu generieren, wie unten gezeigt:

hive -e 'tab_replaced_hql_query' |  python -c 'exec("import sys;import csv;reader = csv.reader(sys.stdin, dialect=csv.excel_tab);writer = csv.writer(sys.stdout, dialect=csv.excel)\nfor row in reader: writer.writerow(row)")'

Dies schuf eine vollkommen gültige CSV. Hoffe, das hilft denen, die nach dieser Lösung suchen.

sisanared
quelle
1
Es ist 2016 und wir müssen noch durch die Reifen springen, um dies zu tun? Ich fand, dass die Lösung von shravster die bisher beste und eleganteste Lösung ist.
Josh
Wie haben Sie alle \ t Zeichen in den Spaltendaten ersetzt? Haben Sie es in der Abfrage angesprochen oder eine separate Ansicht dafür erstellt?
Naresh S
@ NareshS, entschuldige die späte Antwort. Ja, die Spalten wurden im Bienenstock behandelt, um Tabulatoren durch Leerzeichen zu ersetzen, oder wenn sie wesentlich sind, können Sie sie durch einen Ersatz wie <: tab> oder etwas in dieser Richtung
ersetzen
@sisanared, Danke für die Antwort. Ich sehe, wir müssen Regex-Ersetzung für alle Zeichenfolgenspalten verwenden, und dies wäre umständlich, wenn wir eine Tabelle mit einer großen Anzahl von Spalten> 100 haben. Gibt es eine schnelle Lösung für einen solchen Fall
Naresh S
@ NareshS, leider besteht die einzige andere Lösung darin, Daten zu bereinigen, bevor sie in Ihre Partitionen gestellt werden. Andernfalls müssen Sie dies tun, während Sie die Auswahl für alle Zeichenfolgenspalten durchführen, die Tabulatorzeichen enthalten könnten
sisanared
3

Sie können die Hive-String-Funktion verwenden CONCAT_WS( string delimiter, string str1, string str2...strn )

zum Beispiel:

hive -e 'select CONCAT_WS(',',cola,colb,colc...,coln) from Mytable' > /home/user/Mycsv.csv
Ram Ghadiyaram
quelle
2

Ich hatte ein ähnliches Problem und so konnte ich es angehen.

Schritt 1 - Laden Sie die Daten aus der Hive-Tabelle wie folgt in eine andere Tabelle

DROP TABLE IF EXISTS TestHiveTableCSV;
CREATE TABLE TestHiveTableCSV 
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' AS
SELECT Column List FROM TestHiveTable;

Schritt 2 - Kopieren Sie den Blob aus dem Hive-Lager an den neuen Speicherort mit der entsprechenden Erweiterung

Start-AzureStorageBlobCopy
-DestContext $destContext 
-SrcContainer "Source Container"
-SrcBlob "hive/warehouse/TestHiveTableCSV/000000_0"
-DestContainer "Destination Container"
-DestBlob "CSV/TestHiveTable.csv"
Dattatrey Sindol
quelle
2
hive  --outputformat=csv2 -e "select * from yourtable" > my_file.csv

oder

hive  --outputformat=csv2 -e "select * from yourtable" > [your_path]/file_name.csv

Ändern Sie für tsv in den obigen Abfragen einfach csv in tsv und führen Sie Ihre Abfragen aus

Terminator17
quelle
2

Dies ist die csv-freundlichste Methode, mit der ich die Ergebnisse von HiveQL ausgeben konnte.
Sie benötigen keine grep- oder sed-Befehle, um die Daten zu formatieren. Stattdessen unterstützt hive dies. Sie müssen lediglich ein zusätzliches Tag für das Ausgabeformat hinzufügen.

hive --outputformat=csv2 -e 'select * from <table_name> limit 20' > /path/toStore/data/results.csv
Rishabh Sachdeva
quelle
1

Das Standardtrennzeichen ist " ^A". In der Python-Sprache ist es " \x01".

Wenn ich das Trennzeichen ändern möchte, verwende ich SQL wie folgt:

SELECT col1, delimiter, col2, delimiter, col3, ..., FROM table

Betrachten Sie dann das Trennzeichen + " ^A" als neues Trennzeichen.

Moshaholo
quelle
1

Ich habe verschiedene Optionen ausprobiert, aber dies wäre eine der einfachsten Lösungen für Python Pandas:

hive -e 'select books from table' | grep "|" ' > temp.csv

df=pd.read_csv("temp.csv",sep='|')

Sie können auch tr "|" ",""|" konvertieren zu ","

notilas
quelle
0

Ähnlich wie in Rays Antwort oben können Sie mit Hive View 2.0 in Hortonworks Data Platform auch eine Hive-Abfrage ausführen und die Ausgabe dann als CSV speichern.

Schoner
quelle
0

Wenn Sie dies unter Windows tun, können Sie das Python-Skript hivehoney verwenden , um Tabellendaten in die lokale CSV-Datei zu extrahieren.

Es wird:

  1. Melden Sie sich beim Bastion Host an.
  2. pbrun.
  3. kinit.
  4. beeline (mit Ihrer Anfrage).
  5. Speichern Sie das Echo von Anfang an in einer Datei unter Windows.

Führen Sie es so aus:

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
Alex B.
quelle
0

Nur um weitere folgende Schritte nach dem Starten der Abfrage zu behandeln: INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select books from table;

In meinem Fall haben die generierten Daten im temporären Ordner das deflateFormat und sehen folgendermaßen aus:

$ ls
000000_0.deflate  
000001_0.deflate  
000002_0.deflate  
000003_0.deflate  
000004_0.deflate  
000005_0.deflate  
000006_0.deflate  
000007_0.deflate

Hier ist der Befehl, um die Deflate-Dateien zu entpacken und alles in eine CSV-Datei zu packen:

hadoop fs -text "file:///home/lvermeer/temp/*" > /home/lvermeer/result.csv
Johnny Huo
quelle
0

Ich komme vielleicht zu spät, würde aber bei der Antwort helfen:

Echo "COL_NAME1 | COL_NAME2 | COL_NAME3 | COL_NAME4"> SAMPLE_Data.csv hive -e 'Wählen Sie eine eindeutige Konkat (COL_1, "|", COL_2, "|", COL_3, "|", COL_4) aus table_Name, wo Klausel, falls erforderlich;' >> SAMPLE_Data.csv

Anil kumar
quelle
0

Dieser Shell-Befehl druckt das Ausgabeformat in CSV output.txtohne die Spaltenüberschriften.

$ hive --outputformat=csv2 -f 'hivedatascript.hql' --hiveconf hive.cli.print.header=false > output.txt
Varanasi Sai Bhargav
quelle
0

Verwenden Sie den Befehl:

hive -e "benutze [Datenbankname]; wähle * aus [Tabellenname] LIMIT 10;" > /path/to/file/my_file_name.csv

Ich hatte einen riesigen Datensatz, dessen Details ich zu organisieren und die Arten von Angriffen und die Anzahl der einzelnen Typen zu bestimmen versuchte. Ein Beispiel, das ich für meine Praxis verwendet habe, das funktioniert hat (und etwas mehr Details hatte), sieht ungefähr so ​​aus:

hive -e "use DataAnalysis;
select attack_cat, 
case when attack_cat == 'Backdoor' then 'Backdoors' 
when length(attack_cat) == 0 then 'Normal' 
when attack_cat == 'Backdoors' then 'Backdoors' 
when attack_cat == 'Fuzzers' then 'Fuzzers' 
when attack_cat == 'Generic' then 'Generic' 
when attack_cat == 'Reconnaissance' then 'Reconnaissance' 
when attack_cat == 'Shellcode' then 'Shellcode' 
when attack_cat == 'Worms' then 'Worms' 
when attack_cat == 'Analysis' then 'Analysis' 
when attack_cat == 'DoS' then 'DoS' 
when attack_cat == 'Exploits' then 'Exploits' 
when trim(attack_cat) == 'Fuzzers' then 'Fuzzers' 
when trim(attack_cat) == 'Shellcode' then 'Shellcode' 
when trim(attack_cat) == 'Reconnaissance' then 'Reconnaissance' end,
count(*) from actualattacks group by attack_cat;">/root/data/output/results2.csv
Mungai Gachango
quelle