Как вывести результаты запроса HiveQL в CSV?


81

мы хотели бы поместить результаты запроса Hive в файл CSV. Я думал, что команда должна выглядеть так:

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

Когда я запускаю его, он говорит, что он успешно завершен, но я никогда не могу найти файл. Как мне найти этот файл или нужно извлекать данные другим способом?

Ответы:


146

Хотя его можно использовать INSERT OVERWRITEдля получения данных из Hive, это может быть не лучший метод для вашего конкретного случая. Сначала позвольте мне объяснить, что INSERT OVERWRITEэто такое, а затем я опишу метод, который я использую для получения файлов tsv из таблиц Hive.

Согласно руководству , ваш запрос сохранит данные в каталоге в HDFS. Формат не будет csv.

Данные, записанные в файловую систему, сериализуются в виде текста со столбцами, разделенными символом ^ A, и строками, разделенными символами новой строки. Если какой-либо из столбцов не является примитивным типом, эти столбцы сериализуются в формат JSON.

Небольшая модификация (добавление LOCALключевого слова) сохранит данные в локальном каталоге.

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

Когда я запускаю аналогичный запрос, вот как выглядит результат.

[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

Лично я обычно запускаю свой запрос напрямую через Hive в командной строке для такого рода вещей и перенаправляю его в локальный файл следующим образом:

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

Это дает мне файл с разделителями табуляции, который я могу использовать. Надеюсь, это будет полезно и для вас.

Основываясь на этом патче 3682 , я подозреваю, что при использовании Hive 0.11 доступно лучшее решение, но я не могу проверить это сам. Новый синтаксис должен позволять следующее.

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

Надеюсь, это поможет.


2
знаете ли вы какую-либо разницу в производительности между вставкой, перезаписывать локальную и конвейерную, при каком приблизительном объеме это может стать проблемой, а также конвейер гарантирует, что вы получите один файл, поскольку другой подход дает нам каталог, который потенциально нам нужно объединить впоследствии
fd8s0 05

Можно ли экспортировать данные в HDFS как формат файла последовательности?
Nageswaran

1
Я попробовал решение (patch-3682), и оно у меня сработало, за исключением того, что по какой-то причине выходной файл не включал заголовки. Обратите внимание, что я установил hive.cli.print.header = true; в моем .hiverc. Вместо этого заголовки были напечатаны на терминале (что, очевидно, не то, что я хотел).
Питер Коган,

@ lukas-vermeer, когда вы создаете таблицу с помощью метода «INSERT OVERWRITE», информация заголовка теряется. Есть ли способ получить информацию из заголовка?
ML_Passion

Привет, Лукас, как ты заставил свою оболочку работать в файловой системе hadoop?
notilas

23

Если вам нужен файл CSV, вы можете изменить решения Lukas следующим образом (при условии, что вы используете Linux):

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

4
Спасибо за это. Я использую вариант, но он работает очень хорошо. Обратите внимание, что это будет вывод с разделителями-запятыми, не обязательно то, что некоторые люди считают CSV. CSV обычно имеет некоторое форматирование для обработки данных с запятыми (например, данные заключаются в двойные кавычки и двойные двойные кавычки для данных с двойными кавычками). Стоит отметить, что добавление параметра «--hiveconf hive.cli.print.header = True» также приведет к получению ваших заголовков на выходе.
jatal

Это самое чистое решение
Датта

1
Это не удалось для меня, например, для строки даты и времени, в которой был пробел между датой и временем.
williaster

@williaster sed 's / \ t \ + /, / g', это должно помочь в решении этой проблемы.
Sudhakar Chavan

Это не сработает, если в tsv есть текст, содержащий запятые. (потому что невинные строковые запятые без кавычек будут рассматриваться как разделители)
yahiaelgamal

4

Вы должны использовать оператор CREATE TABLE AS SELECT (CTAS) для создания каталога в HDFS с файлами, содержащими результаты запроса. После этого вам нужно будет экспортировать эти файлы из HDFS на ваш обычный диск и объединить их в один файл.

Вам также, возможно, придется проделать некоторые хитрости, чтобы преобразовать файлы из '\ 001' с разделителями в CSV. Вы можете использовать собственный CSV-файл SerDe или выполнить постобработку извлеченного файла.


Этот подход лучше всего, если вы хотите использовать вывод на следующем этапе конвейера oozie.
cerd

4

Вы можете использовать INSERT…… DIRECTORYкак в этом примере:

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

OVERWRITEи LOCALимеют те же интерпретации, что и раньше, а пути интерпретируются в соответствии с обычными правилами. Будет произведена запись в один или несколько файлов, в /tmp/ca_employeesзависимости от количества задействованных редукторов.


3

Если вы используете HUE, это тоже довольно просто. Просто перейдите в редактор Hive в HUE, выполните запрос улья, затем сохраните файл результатов локально как XLS или CSV, или вы можете сохранить файл результатов в HDFS.


3

Я искал подобное решение, но упомянутые здесь не работали. В моих данных были все варианты пробелов (пробел, новая строка, табуляция), символов и запятых.

Чтобы сделать tsv данных столбца безопасным, я заменил все символы \ t в данных столбца пробелом и выполнил код python в командной строке для создания файла csv, как показано ниже:

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

Это создало совершенно корректный csv. Надеюсь, это поможет тем, кто ищет это решение.


1
Это 2016 год, и нам еще предстоит преодолеть препятствия, чтобы сделать это? Я нашел решение Шравстера лучшим и самым элегантным решением.
Джош

Как вы заменили все символы \ t в данных столбца? вы указали его в запросе или создали для него отдельное представление?
Naresh S

@NareshS, извините за поздний ответ. Да, столбцы обрабатывались в улье для замены табуляции пробелами или, если они необходимы, вы могли заменить заменой вроде <: tab> или чем-то в этом роде
sisanared

@sisanared, спасибо за ответ. Я вижу, что нам нужно использовать замену регулярных выражений для всех строковых столбцов, и это было бы обременительно, если бы у нас была таблица с большим количеством столбцов> 100. Есть ли быстрое решение для такого случая
Naresh S

@NareshS, к сожалению, единственное другое решение - очистить данные, прежде чем помещать их в свои разделы. В противном случае вам придется делать это при выполнении выбора для всех строковых столбцов, которые могут содержать символы табуляции
sisanared

3

Вы можете использовать строковую функцию улья CONCAT_WS( string delimiter, string str1, string str2...strn )

например:

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

3

Это наиболее удобный для csv способ вывода результатов HiveQL.
Вам не нужны никакие команды grep или sed для форматирования данных, вместо этого hive поддерживает их, просто нужно добавить дополнительный тег outputformat.

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

2

У меня была аналогичная проблема, и вот как я смог ее решить.

Шаг 1. Загрузили данные из таблицы Hive в другую таблицу следующим образом.

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

Шаг 2. Скопируйте большой двоичный объект со склада Hive в новое место с соответствующим расширением.

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

или же

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

Для tsv просто измените csv на tsv в приведенных выше запросах и запустите свои запросы.


1

Разделитель по умолчанию - " ^A". На языке Python это "\x01 ".

Когда я хочу изменить разделитель, я использую SQL, например:

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

Затем рассмотрите разделитель + " ^A" как новый разделитель.


1

Я пробовал разные варианты, но это было бы одно из самых простых решений Python Pandas:

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

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

Вы также можете использовать tr "|" ","для преобразования "|" к ","


0

Подобно ответу Рэя выше, Hive View 2.0 на платформе данных Hortonworks также позволяет запускать запрос Hive, а затем сохранять результат как csv.


0

Если вы делаете это из Windows, вы можете использовать скрипт Python hivehoney для извлечения данных таблицы в локальный файл CSV.

Так и будет:

  1. Авторизуйтесь на хосте бастиона
  2. pbrun.
  3. кинит.
  4. билайн (по вашему запросу).
  5. Сохраните эхо из билайн в файл в Windows.

Выполните это так:

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

Просто чтобы охватить больше следующих шагов после запуска запроса: INSERT OVERWRITE LOCAL DIRECTORY '/home/lvermeer/temp' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select books from table;

В моем случае сгенерированные данные в папке temp имеют deflateформат и выглядят так:

$ 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

Вот команда, чтобы распаковать файлы deflate и поместить все в один файл csv:

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

0

Я могу опоздать к этому, но помогу с ответом:

echo "COL_NAME1 | COL_NAME2 | COL_NAME3 | COL_NAME4"> SAMPLE_Data.csv куст -e 'выбрать отдельный concat (COL_1, "|", COL_2, "|", COL_3, "|", COL_4) из table_Name, где условие, если требуется;' >> SAMPLE_Data.csv


0

Эта команда оболочки выводит выходной формат в формате CSV output.txtбез заголовков столбцов.

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

0

Используйте команду:

hive -e "использовать [имя_базы_данных]; выбрать * из [имя_таблицы] LIMIT 10;" > /path/to/file/my_file_name.csv

У меня был огромный набор данных , детали которого я пытался систематизировать и определить типы атак и количество каждого типа. Пример, который я использовал в своей практике, который работал (и имел немного больше деталей), выглядит примерно так:

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.