web-dev-qa-db-fra.com

Hive: écrire des en-têtes de colonne dans un fichier local?

La documentation de la ruche manque encore:

Je voudrais écrire les résultats d'une requête dans un fichier local ainsi que les noms des colonnes.

Est-ce que Hive le supporte?

Insert overwrite local directory 'tmp/blah.blah' select * from table_name;

Aussi, question distincte: StackOverflow est-il le meilleur endroit pour obtenir de l'aide sur Hive? @Nija, a été très utile, mais je ne les dérange pas ...

28
CMaury

Hive prend en charge l'écriture dans le répertoire local. La syntaxe vous convient également.
Consultez les documents sur SELECTS et FILTERS pour plus d'informations.

Je ne pense pas que Hive ait un moyen d'écrire les noms des colonnes dans un fichier pour la requête que vous exécutez. . . Je ne peux pas dire avec certitude que non, mais je ne connais pas de moyen.

Je pense que le seul endroit meilleur que SO pour les questions Hive serait la liste de diffusion .

6
QuinnG

Essayer

set Hive.cli.print.header=true;
64
iggy

Oui, vous pouvez. Mettez le set Hive.cli.print.header=true; dans un .hiverc fichier dans votre répertoire principal ou dans tout autre fichier de propriétés utilisateur Hive.

Vague Warning: soyez prudent, car cela a fait planter mes requêtes dans le passé (mais je ne me souviens pas de la raison).

15
Dan B

En effet, la réponse de @ nija est correcte - du moins pour autant que je sache. Il n'y a aucun moyen d'écrire les noms des colonnes lorsque vous effectuez un insert overwrite into [local] directory ... (que vous utilisiez local ou non).

En ce qui concerne les plantages décrits par @ user1735861, il existe un bogue connu dans Hive 0.7.1 (corrigé dans 0.8.0) qui, après avoir fait set Hive.cli.print.header=true;, provoque un NullPointerException pour toute commande/requête HQL qui ne produit aucune sortie. Par exemple:

 $ Hive -S 
 Hive> utiliser par défaut; 
 Hive> définir Hive.cli.print.header = true; 
 Hive> utiliser la valeur par défaut; 
 Exception dans le thread "principal" Java.lang.NullPointerException 
 À org.Apache.hadoop.Hive.cli.CliDriver.processCmd (CliDriver.Java:222) 
 sur org.Apache.hadoop.Hive.cli.CliDriver.processLine (CliDriver.Java:287) 
 sur org.Apache.hadoop.Hive.cli.CliDriver.main (CliDriver.Java:517) 
 sur Sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) 
 sur Sun.reflect.NativeMethodAccessorImplpl .invoke (NativeMethodAccessorImpl.Java:57) 
 sur Sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.Java:43) 
 sur Java.lang.reflect.Method.invoke (Method.Java:616) ) 
 sur org.Apache.hadoop.util.RunJar.main (RunJar.Java:197) 

Alors que c'est bien:

 $ Hive -S 
 Hive> set Hive.cli.print.header = true; 
 Hive> select * from dual; 
 C 
 c 
 Ruche> 

Les commandes non HQL sont très bien cependant (set, dfs!, etc...)

Plus d'informations ici: https://issues.Apache.org/jira/browse/Hive-2334

9
Hercynium

J'ai rencontré ce problème aujourd'hui et j'ai pu obtenir ce dont j'avais besoin en effectuant UNION ALL entre la requête d'origine et une nouvelle requête fictive qui crée la ligne d'en-tête. J'ai ajouté une colonne de tri sur chaque section et mis l'en-tête à 0 et les données à 1 afin que je puisse trier par ce champ et m'assurer que la ligne d'en-tête est sortie en haut.

create table new_table as
select 
  field1,
  field2,
  field3
from
(
  select
    0 as sort_col,  --header row gets lowest number
    'field1_name' as field1,
    'field2_name' as field2,
    'field3_name' as field3
  from
    some_small_table  --table needs at least 1 row
  limit 1  --only need 1 header row
  union all
  select
    1 as sort_col,  --original query goes here
    field1,
    field2,
    field3
  from
    main_table
) a
order by 
  sort_col  --make sure header row is first

C'est un peu volumineux, mais au moins vous pouvez obtenir ce dont vous avez besoin avec une seule requête.

J'espère que cela t'aides!

4
McLeodComputing

Pas une bonne solution, mais voici ce que je fais:

create table test_dat
ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t" STORED AS 
INPUTFORMAT "com.hadoop.mapred.DeprecatedLzoTextInputFormat" 
OUTPUTFORMAT "org.Apache.hadoop.Hive.ql.io.HiveIgnoreKeyTextOutputFormat" 
LOCATION '/tmp/test_dat' as select * from YOUR_TABLE;

Hive -e 'set Hive.cli.print.header=true;select * from YOUR_TABLE limit 0' > /tmp/test_dat/header.txt

cat header.txt 000* > all.dat
3
Jeremy

Voici mon point de vue là-dessus. Remarque, je ne connais pas très bien bash, donc les suggestions d'améliorations sont les bienvenues :)

#!/usr/bin/env bash

# works like this:
# ./get_data.sh database.table > data.csv

INPUT=$1
TABLE=${INPUT##*.}
DB=${INPUT%.*}

HEADER=`Hive -e "
  set Hive.cli.print.header=true;
  use $DB;
  INSERT OVERWRITE LOCAL DIRECTORY '$TABLE'
  row format delimited
  fields terminated  by ','
  SELECT * FROM $TABLE;"`

HEADER_WITHOUT_TABLE_NAME=${HEADER//$TABLE./}
echo ${HEADER_WITHOUT_TABLE_NAME//[[:space:]]/,}
cat $TABLE/*
2
tdgs