Làm cách nào để xuất kết quả của truy vấn HiveQL sang CSV?


81

chúng tôi muốn đưa kết quả của truy vấn Hive vào tệp CSV. Tôi nghĩ lệnh sẽ trông như thế này:

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

Khi tôi chạy nó, nó nói rằng nó hoàn thành thành công nhưng tôi không bao giờ có thể tìm thấy tệp. Làm cách nào để tìm tệp này hoặc tôi nên trích xuất dữ liệu theo một cách khác?

Câu trả lời:


146

Mặc dù có thể sử dụng INSERT OVERWRITEđể lấy dữ liệu ra khỏi Hive, nhưng nó có thể không phải là phương pháp tốt nhất cho trường hợp cụ thể của bạn. Đầu tiên hãy để tôi giải thích những gì INSERT OVERWRITElàm được, sau đó tôi sẽ mô tả phương pháp tôi sử dụng để lấy tệp tsv từ bảng Hive.

Theo hướng dẫn , truy vấn của bạn sẽ lưu trữ dữ liệu trong một thư mục trong HDFS. Định dạng sẽ không phải là csv.

Dữ liệu được ghi vào hệ thống tệp được tuần tự hóa dưới dạng văn bản với các cột được phân tách bằng ^ A và các hàng được phân tách bằng dòng mới. Nếu bất kỳ cột nào không thuộc kiểu nguyên thủy, thì các cột đó được tuần tự hóa thành định dạng JSON.

Một sửa đổi nhỏ (thêm LOCALtừ khóa) sẽ lưu trữ dữ liệu trong một thư mục cục bộ.

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

Khi tôi chạy một truy vấn tương tự, đây là kết quả đầu ra.

[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

Cá nhân tôi thường chạy truy vấn của mình trực tiếp thông qua Hive trên dòng lệnh cho loại điều này và chuyển nó vào tệp cục bộ như sau:

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

Điều đó cung cấp cho tôi một tệp được phân tách bằng tab mà tôi có thể sử dụng. Hy vọng điều đó cũng hữu ích cho bạn.

Dựa trên bản vá-3682 này , tôi nghi ngờ có giải pháp tốt hơn khi sử dụng Hive 0.11, nhưng tôi không thể tự mình kiểm tra điều này. Cú pháp mới sẽ cho phép những điều sau.

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

Hy vọng rằng sẽ giúp.


2
bạn có biết bất kỳ sự khác biệt về hiệu suất nào giữa chèn ghi đè cục bộ và đường ống, ở đó khối lượng xấp xỉ nó có thể trở thành một vấn đề, ngoài ra, đường ống đảm bảo bạn sẽ nhận được một tệp, vì cách tiếp cận khác cung cấp cho chúng tôi một thư mục mà chúng tôi có thể cần hợp nhất sau đó
fd8s0

Có thể xuất dữ liệu ở định dạng HDFS dưới dạng tệp Trình tự không?
Nageswaran,

1
Tôi đã thử giải pháp (bản vá-3682) và nó hoạt động tốt đối với tôi - ngoại trừ một số lý do mà tệp đầu ra không bao gồm các tiêu đề. Lưu ý rằng tôi đã đặt hive.cli.print.header = true; trong .hiverc của tôi. Đối với những gì nó đáng giá các tiêu đề được in vào thiết bị đầu cuối thay thế (điều này rõ ràng không phải là những gì tôi muốn).
Peter Cogan

@ lukas-vermeer, khi bạn tạo bảng bằng phương pháp "CHÈN TRÊN TRANG WEB", thông tin tiêu đề bị mất. Có cách nào để lấy thông tin tiêu đề?
ML_Passion

Xin chào Lukas, bạn đã làm cách nào để trình bao của mình hoạt động trong hệ thống tệp hadoop?
notilas

23

Nếu bạn muốn có tệp CSV thì bạn có thể sửa đổi các giải pháp của Lukas như sau (giả sử bạn đang sử dụng hộp linux):

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

4
Cám ơn vì cái này. Tôi đang sử dụng một biến thể, nhưng nó hoạt động rất tốt. Xin lưu ý rằng điều này sẽ xuất ra được phân tách bằng dấu phẩy, không nhất thiết là thứ mà một số người nghĩ là CSV. CSV thường có một số định dạng để xử lý dữ liệu có dấu phẩy (ví dụ: bọc dữ liệu bằng dấu ngoặc kép và dấu ngoặc kép đối với dữ liệu có dấu ngoặc kép). Đáng nói là việc thêm tham số "--hiveconf hive.cli.print.header = True" cũng sẽ nhận được tiêu đề của bạn trong đầu ra.
jatal

Đây là giải pháp sạch nhất
Dutta

1
Điều này không thành công đối với tôi, ví dụ: một chuỗi ngày giờ có khoảng cách giữa ngày và giờ.
williaster

@williaster sed 's / \ t \ + /, / g' điều này sẽ hữu ích cho vấn đề này.
Sudhakar Chavan

Điều này sẽ không hoạt động nếu tsv có văn bản chứa dấu phẩy. (vì không thể viện chứng dấu phẩy chuỗi vô tội sẽ được coi như tách)
yahiaelgamal

4

Bạn nên sử dụng câu lệnh CREATE TABLE AS SELECT (CTAS) để tạo một thư mục trong HDFS với các tệp chứa kết quả của truy vấn. Sau đó, bạn sẽ phải xuất các tệp đó từ HDFS sang đĩa thông thường của mình và hợp nhất chúng thành một tệp duy nhất.

Bạn cũng có thể phải thực hiện một số thủ thuật để chuyển đổi các tệp từ '\ 001' - được phân tách thành CSV. Bạn có thể sử dụng SerDe CSV tùy chỉnh hoặc xử lý hậu kỳ tệp đã trích xuất.


Cách tiếp cận này là tốt nhất nếu một người muốn sử dụng đầu ra trong bước tiếp theo của quy trình oozie.
cerd

4

Bạn có thể sử dụng INSERT…… DIRECTORY, như trong ví dụ này:

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

OVERWRITELOCALcó các cách diễn giải giống như trước và các đường dẫn được diễn giải theo các quy tắc thông thường. Một hoặc nhiều tệp sẽ được ghi vào /tmp/ca_employees, tùy thuộc vào số lượng bộ giảm được gọi.


3

Nếu bạn đang sử dụng HUE, điều này cũng khá đơn giản. Chỉ cần truy cập trình chỉnh sửa Hive trong HUE, thực hiện truy vấn hive của bạn, sau đó lưu tệp kết quả cục bộ dưới dạng XLS hoặc CSV hoặc bạn có thể lưu tệp kết quả vào HDFS.


3

Tôi đã tìm kiếm một giải pháp tương tự, nhưng những giải pháp được đề cập ở đây sẽ không hoạt động. Dữ liệu của tôi có tất cả các biến thể của ký tự khoảng trắng (dấu cách, dòng mới, tab) và dấu phẩy.

Để làm cho dữ liệu cột tsv an toàn, tôi đã thay thế tất cả các ký tự trong dữ liệu cột bằng một khoảng trắng và thực thi mã python trên dòng lệnh để tạo tệp csv, như được hiển thị bên dưới:

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

Điều này đã tạo ra một csv hoàn toàn hợp lệ. Hy vọng điều này sẽ giúp những người tìm kiếm giải pháp này.


1
Đó là năm 2016 và chúng ta vẫn phải nhảy qua các vòng để làm điều này? Tôi thấy giải pháp của shravster là giải pháp tốt nhất, thanh lịch nhất cho đến nay.
Josh

Bạn đã thay thế tất cả các ký tự trong dữ liệu cột như thế nào? bạn đã giải quyết nó trong truy vấn hay tạo một dạng xem riêng cho nó?
Naresh S

@NareshS, xin lỗi vì phản hồi muộn. Có, các cột được xử lý trong tổ ong để thay thế các tab bằng dấu cách hoặc nếu chúng cần thiết, bạn có thể thay thế bằng một thay thế như <: tab> hoặc một cái gì đó dọc theo các dòng đó
sisanared

@sisanared, Cảm ơn bạn đã phản hồi. Tôi thấy chúng ta cần phải sử dụng regex thay thế cho tất cả các cột dây và điều này sẽ là rườm rà nếu chúng ta có một bảng với số lượng lớn các colums> 100. Có một giải pháp nhanh chóng cho trường hợp này
Naresh S

@NareshS, thật không may, giải pháp khác duy nhất là dọn dẹp dữ liệu trước khi đưa nó vào phân vùng của bạn. Nếu không, bạn sẽ phải làm điều đó trong khi thực hiện chọn cho tất cả các cột chuỗi có thể chứa ký tự tab
quản lý vào

3

Bạn có thể sử dụng hàm chuỗi tổ ong CONCAT_WS( string delimiter, string str1, string str2...strn )

cho người yêu cũ:

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

3

Đây là cách thân thiện nhất với csv mà tôi tìm thấy để xuất ra kết quả của HiveQL.
Bạn không cần bất kỳ lệnh grep hoặc sed nào để định dạng dữ liệu, thay vào đó, hive hỗ trợ nó, chỉ cần thêm thẻ phụ của outputformat.

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

2

Tôi đã gặp vấn đề tương tự và đây là cách tôi có thể giải quyết nó.

Bước 1 - Đã tải dữ liệu từ bảng Hive vào một bảng khác như sau

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

Bước 2 - Sao chép đốm màu từ kho Hive sang vị trí mới với phần mở rộng thích hợp

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

hoặc là

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

Đối với tsv, chỉ cần thay đổi csv thành tsv trong các truy vấn ở trên và chạy các truy vấn của bạn


1

Dấu phân tách mặc định là " ^A". Trong ngôn ngữ python, nó là " \x01".

Khi tôi muốn thay đổi dấu phân cách, tôi sử dụng SQL như:

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

Sau đó, coi dấu phân tách + " ^A" là dấu phân cách mới.


1

Tôi đã thử các tùy chọn khác nhau, nhưng đây sẽ là một trong những giải pháp đơn giản nhất cho Python Pandas:

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

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

Bạn cũng có thể sử dụng tr "|" ","để chuyển đổi "|" đến ","


0

Tương tự như câu trả lời của Ray ở trên, Hive View 2.0 trong Nền tảng dữ liệu Hortonworks cũng cho phép bạn chạy một truy vấn Hive và sau đó lưu đầu ra dưới dạng csv.


0

Trong trường hợp bạn đang làm điều đó từ Windows, bạn có thể sử dụng tập lệnh Python hivehoney để trích xuất dữ liệu bảng sang tệp CSV cục bộ.

Nó sẽ:

  1. Đăng nhập vào máy chủ pháo đài.
  2. pbrun.
  3. kim loại.
  4. beeline (với truy vấn của bạn).
  5. Lưu tiếng vọng từ beeline vào một tệp trên Windows.

Thực thi nó như thế này:

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

Chỉ để trình bày thêm các bước sau sau khi bắt đầu truy vấn: INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select books from table;

Trong trường hợp của tôi, dữ liệu được tạo trong thư mục tạm thời có deflateđịnh dạng và có dạng như sau:

$ 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

Đây là lệnh để giải nén các tệp deflate và đưa mọi thứ vào một tệp csv:

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

0

Tôi có thể đến muộn với câu hỏi này, nhưng sẽ giúp trả lời:

echo "COL_NAME1 | COL_NAME2 | COL_NAME3 | COL_NAME4"> SAMPLE_Data.csv hive -e 'select concat riêng biệt (COL_1, "|", COL_2, "|", COL_3, "|", COL_4) từ table_Name where mệnh đề nếu được yêu cầu;' >> SAMPLE_Data.csv


0

Lệnh shell này in định dạng đầu ra trong csv output.txtmà không có tiêu đề cột.

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

0

Sử dụng lệnh:

hive -e "sử dụng [tên_cơ_liệu]; chọn * từ [tên_bảng] LIMIT 10;" > /path/to/file/my_file_name.csv

Tôi đã có một tập dữ liệu khổng lồ với chi tiết mà tôi đang cố gắng tổ chức và xác định các loại tấn công và số lượng của từng loại. Một ví dụ mà tôi đã sử dụng trong thực tế của mình đã hoạt động (và có thêm một chút chi tiết) như sau:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.