Jak wyprowadzić wyniki zapytania HiveQL do pliku CSV?


81

chcielibyśmy umieścić wyniki zapytania Hive w pliku CSV. Pomyślałem, że polecenie powinno wyglądać tak:

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

Kiedy go uruchamiam, mówi, że zakończyło się pomyślnie, ale nigdy nie mogę znaleźć pliku. Jak znaleźć ten plik, czy powinienem wyodrębniać dane w inny sposób?

Odpowiedzi:


146

Chociaż można użyć INSERT OVERWRITEdo pobrania danych z Hive, może to nie być najlepsza metoda w Twoim konkretnym przypadku. Najpierw wyjaśnię, co to INSERT OVERWRITErobi, a następnie opiszę metodę, której używam do pobierania plików tsv z tabel Hive.

Zgodnie z instrukcją , twoje zapytanie zapisze dane w katalogu w HDFS. Format nie będzie csv.

Dane zapisywane w systemie plików są serializowane jako tekst z kolumnami oddzielonymi ^ A i wierszami oddzielonymi znakami nowej linii. Jeśli którakolwiek z kolumn nie jest typu pierwotnego, te kolumny są serializowane do formatu JSON.

Niewielka modyfikacja (dodanie LOCALsłowa kluczowego) spowoduje zapisanie danych w katalogu lokalnym.

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

Kiedy uruchamiam podobne zapytanie, oto jak wygląda wynik.

[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

Osobiście zwykle uruchamiam zapytanie bezpośrednio przez Hive w wierszu poleceń i przesyłam je do lokalnego pliku w następujący sposób:

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

To daje mi plik rozdzielany tabulatorami, którego mogę użyć. Mam nadzieję, że ci się to przyda.

W oparciu o tę poprawkę-3682 podejrzewam, że lepsze rozwiązanie jest dostępne podczas korzystania z Hive 0.11, ale nie jestem w stanie tego samodzielnie przetestować. Nowa składnia powinna umożliwiać następujące czynności.

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

Mam nadzieję, że to pomoże.


2
czy znasz jakąkolwiek różnicę w wydajności między wstawianiem nadpisywania lokalnego a potokiem, przy której przybliżonej objętości może to stać się problemem, a także piping gwarantuje, że otrzymasz jeden plik, ponieważ drugie podejście daje nam katalog, który potencjalnie musimy później scalić
fd8s0

Czy można wyeksportować dane w formacie HDFS jako plik sekwencji?
Nageswaran

1
Wypróbowałem rozwiązanie (patch-3682) i działało dobrze - poza tym, że z jakiegoś powodu plik wyjściowy nie zawierał nagłówków. Zauważ, że ustawiłem hive.cli.print.header = true; w moim .hiverc. Ale co jest warte, nagłówki zostały wydrukowane na terminalu (co oczywiście nie jest tym, czego chciałem).
Peter Cogan

@ lukas-vermeer, kiedy tworzysz tabelę za pomocą metody „INSERT OVERWRITE”, informacje nagłówka są tracone. Czy istnieje sposób na uzyskanie informacji nagłówka?
ML_Passion

Cześć Lukas, jak sprawiłeś, że twoja powłoka działa w systemie plików hadoop?
notilas

23

Jeśli chcesz plik CSV, możesz zmodyfikować rozwiązania Lukasa w następujący sposób (zakładając, że używasz Linuksa):

hive -e 'select books from table' | sed 's/[[:space:]]\+/,/g' > /home/lvermeer/temp.csv

4
Dzięki za to. Używam odmiany, ale działa bardzo dobrze. Zwróć uwagę, że spowoduje to rozdzielenie przecinkami, niekoniecznie to, co niektórzy myślą jako CSV. CSV ma zwykle pewne formatowanie do obsługi danych przecinkami (np. Zawijanie danych w cudzysłowy, a podwójne cudzysłowy w przypadku danych w cudzysłowach). Warto wspomnieć, że dodanie parametru "--hiveconf hive.cli.print.header = True" spowoduje również wyświetlenie nagłówków.
jatal

To najczystsze rozwiązanie
Dutta

1
Nie udało mi się to na przykład w przypadku ciągu daty i godziny, który zawierał spację między datą a godziną.
williaster

@williaster sed 's / \ t \ + /, / g' to powinno pomóc w tym problemie.
Sudhakar Chavan

To nie zadziała, jeśli tsv zawiera tekst zawierający przecinki. (ponieważ niecytowane niewinne przecinki będą traktowane jako separatory)
yahiaelgamal

4

Należy użyć instrukcji CREATE TABLE AS SELECT (CTAS), aby utworzyć katalog w systemie plików HDFS z plikami zawierającymi wyniki zapytania. Następnie będziesz musiał wyeksportować te pliki z HDFS na zwykły dysk i scalić je w jeden plik.

Być może będziesz musiał zrobić trochę sztuczki, aby przekonwertować pliki z „\ 001” - rozdzielone na CSV. Możesz użyć niestandardowego CSV SerDe lub przetworzyć wyodrębniony plik.


To podejście jest najlepsze, jeśli chcesz użyć danych wyjściowych w kolejnym kroku potoku oozie.
cerd

4

Możesz użyć INSERT…… DIRECTORY, jak w tym przykładzie:

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

OVERWRITEi LOCALmają takie same interpretacje jak poprzednio, a ścieżki są interpretowane zgodnie ze zwykłymi zasadami. W /tmp/ca_employeeszależności od liczby wywoływanych redukcji zostanie zapisany jeden lub więcej plików .


3

Jeśli używasz HUE, jest to również dość proste. Po prostu przejdź do edytora Hive w HUE, wykonaj zapytanie gałęzi, a następnie zapisz plik wynikowy lokalnie jako XLS lub CSV albo możesz zapisać plik wynikowy w formacie HDFS.


3

Szukałem podobnego rozwiązania, ale te wymienione tutaj nie zadziałały. Moje dane zawierały wszystkie odmiany białych znaków (spacja, nowa linia, tabulacja), znaki i przecinki.

Aby zabezpieczyć dane tsv w kolumnie, zastąpiłem wszystkie znaki \ t w danych kolumny spacją i wykonałem kod Pythona w wierszu poleceń, aby wygenerować plik csv, jak pokazano poniżej:

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)")'

Stworzyło to doskonale poprawny plik CSV. Mam nadzieję, że pomoże to tym, którzy szukają tego rozwiązania.


1
Jest rok 2016 i nadal musimy skakać przez obręcze, aby to zrobić? Rozwiązanie Shravstera okazało się jak dotąd najlepszym, najbardziej eleganckim rozwiązaniem.
Josh

W jaki sposób zastąpiłeś wszystkie \ t znaki w danych kolumny? czy adresowałeś to w zapytaniu czy utworzyłeś dla niego osobny widok?
Naresh S,

@NareshS, przepraszam za spóźnioną odpowiedź. Tak, kolumny były obsługiwane w gałęzi w celu zastąpienia tabulatorów spacjami lub, jeśli są niezbędne, można je zastąpić zamiennikiem, takim jak <: tab> lub czymś
podobnym

@sisanared, Dzięki za odpowiedź. Widzę, że musimy użyć zamiany wyrażenia regularnego dla wszystkich kolumn ciągów i byłoby to kłopotliwe, gdybyśmy mieli tabelę z dużą liczbą kolumn> 100. Czy istnieje szybkie rozwiązanie w takim przypadku
Naresh S

@NareshS, niestety jedynym innym rozwiązaniem jest wyczyszczenie danych przed umieszczeniem ich na partycjach. W przeciwnym razie będziesz musiał to zrobić podczas wybierania dla wszystkich kolumn ciągów, które mogą zawierać znaki tabulacji
sisanared

3

Możesz użyć funkcji ciągów gałęzi CONCAT_WS( string delimiter, string str1, string str2...strn )

na przykład:

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

3

Jest to najbardziej przyjazny dla csv sposób, jaki znalazłem, aby wyświetlić wyniki HiveQL.
Nie potrzebujesz żadnych poleceń grep ani sed do formatowania danych, zamiast tego hive je obsługuje, wystarczy dodać dodatkowy znacznik formatu outputformat.

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

2

Miałem podobny problem i tak udało mi się go rozwiązać.

Krok 1 - Załaduj dane z tabeli Hive do innej tabeli w następujący sposób

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

Krok 2 - skopiowano obiekt blob z magazynu Hive do nowej lokalizacji z odpowiednim rozszerzeniem

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

2
hive  --outputformat=csv2 -e "select * from yourtable" > my_file.csv

lub

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

W przypadku tsv po prostu zmień csv na tsv w powyższych zapytaniach i uruchom zapytania


1

Domyślnym separatorem jest „ ^A”. W języku Python jest to „ \x01”.

Kiedy chcę zmienić separator, używam SQL jak:

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

Następnie potraktuj separator + " ^A" jako nowy separator.


1

Wypróbowałem różne opcje, ale byłoby to jedno z najprostszych rozwiązań dla Python Pandas:

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

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

Możesz także użyć tr "|" ","do konwersji „|” do ","


0

Podobnie jak w przypadku powyższej odpowiedzi Raya, Hive View 2.0 w Hortonworks Data Platform umożliwia również uruchomienie zapytania Hive, a następnie zapisanie wyniku w formacie csv.


0

Jeśli robisz to w systemie Windows, możesz użyć skryptu hivehoney w języku Python, aby wyodrębnić dane tabeli do lokalnego pliku CSV.

To będzie:

  1. Zaloguj się do hosta bastionu.
  2. pbrun.
  3. kinit.
  4. beeline (z zapytaniem).
  5. Zapisz echo z beeline do pliku w systemie Windows.

Wykonaj to w ten sposób:

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

0

Aby po uruchomieniu zapytania omówić więcej następujących kroków: INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select books from table;

W moim przypadku wygenerowane dane w folderze tymczasowym są w deflateformacie i wygląda to tak:

$ 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

Oto polecenie rozpakowania plików deflate i umieszczenia wszystkiego w jednym pliku csv:

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

0

Mogę się spóźnić na ten, ale pomogę w odpowiedzi:

echo "COL_NAME1 | COL_NAME2 | COL_NAME3 | COL_NAME4"> SAMPLE_Data.csv gałąź -e 'wybierz odrębne konkatowanie (COL_1, "|", COL_2, "|", COL_3, "|", COL_4) z table_Name, gdzie klauzula, jeśli jest wymagana;' >> SAMPLE_Data.csv


0

To polecenie powłoki drukuje format wyjściowy w csv output.txtbez nagłówków kolumn.

$ hive --outputformat=csv2 -f 'hivedatascript.hql' --hiveconf hive.cli.print.header=false > output.txt

0

Użyj polecenia:

hive -e "use [nazwa_bazy_danych]; wybierz * z [nazwa_tabeli] LIMIT 10;" > /ścieżka/do/plik/nazwa_moje_pliku.csv

Miałem ogromny zbiór danych, którego szczegóły starałem się uporządkować i określić rodzaje ataków oraz ich liczbę. Przykład, którego użyłem w mojej praktyce, który zadziałał (i miał trochę więcej szczegółów), wygląda mniej więcej tak:

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.