web-dev-qa-db-fra.com

La sortie de la commande Hive INSERT OVERWRITE DIRECTORY n'est pas séparée par un délimiteur. Pourquoi?

Le fichier que je charge est séparé par '' (espace blanc). Ci-dessous le fichier. Le fichier réside dans HDFS: -

001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

1> Je crée une table externe et charge le fichier en lançant la commande ci-dessous: -

CREATE EXTERNAL TABLE IF NOT EXISTS graph_edges (src_node_id STRING COMMENT 'Node ID of Source node', dest_node_id STRING COMMENT 'Node ID of Destination node') ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' STORED AS TEXTFILE LOCATION '/user/hadoop/input';

2> Après cela, j'insère simplement la table dans un autre fichier en émettant la commande ci-dessous: -

INSERT OVERWRITE DIRECTORY '/user/hadoop/output' SELECT * FROM graph_edges;

3> Maintenant, quand je cloue le fichier, les champs ne sont séparés par aucun délimiteur: -

hadoop dfs -cat /user/hadoop/output/000000_0

Sortie:-

001000
001000
002001
003002
004003
005004
006005
007006
008007
099007

Quelqu'un peut-il m'aider s'il vous plaît? Pourquoi le délimiteur est-il supprimé et comment délimiter le fichier de sortie?

Dans la commande CREATE TABLE, j'ai essayé DELIMITED BY '\t' mais la colonne NULL devient inutile.

Tous les pointeurs aident beaucoup apprécié. J'utilise la version 0.9.0 de Hive.

11
Anuroop

Le problème est que Hive ne vous permet pas de spécifier le délimiteur de sortie - https://issues.Apache.org/jira/browse/Hive-634

La solution consiste à créer une table externe pour la sortie (avec la spécification de délimiteur) et à insérer une table de remplacement au lieu d'un répertoire.

-

En supposant que vous avez /user/hadoop/input/graph_edges.csv dans HDFS, 

Hive> create external table graph_edges (src string, dest string) 
    > row format delimited 
    > fields terminated by ' ' 
    > lines terminated by '\n' 
    > stored as textfile location '/user/hadoop/input';

Hive> select * from graph_edges;
OK
001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

Hive> create external table graph_out (src string, dest string) 
    > row format delimited 
    > fields terminated by ' ' 
    > lines terminated by '\n' 
    > stored as textfile location '/user/hadoop/output';

Hive> insert into table graph_out select * from graph_edges;
Hive> select * from graph_out;
OK
001 000
001 000
002 001
003 002
004 003
005 004
006 005
007 006
008 007
099 007

[user@box] hadoop fs -get /user/hadoop/output/000000_0 .

Revient comme ci-dessus, avec des espaces.

16
kgu87

Alors que la question a plus de 2 ans et que la première réponse était correcte à l'époque, il est maintenant possible de dire à Hive d'écrire des données délimitées dans un répertoire. 

Voici un exemple de sortie des données avec le séparateur traditionnel ^ A:

INSERT OVERWRITE DIRECTORY '/output/data_delimited'
SELECT *
FROM data_schema.data_table

Et maintenant, avec les délimiteurs de tabulation:

INSERT OVERWRITE DIRECTORY '/output/data_delimited'
row format delimited 
FIELDS TERMINATED BY '\t'
SELECT *
FROM data_schema.data_table
9
Garren S

Je pense qu'en utilisant la fonction concat_ws, vous pouvez obtenir votre résultat.

INSERT OVERWRITE DIRECTORY '/ utilisateur/hadoop/sortie' SELECT concat_ws (',', col1, col2) FROM graph_edges;

ici j'ai choisi la virgule comme séparateur de colonne

9
Sid

J'ai une voix différente.

En effet, Hive ne prend pas en charge le délimiteur personnalisé.

Mais lorsque vous utilisez INSERT OVERWRITE DIRECTORY, il y a des délimiteurs dans vos lignes. Le délimiteur est '\1'

Vous pouvez utiliser hadoop dfs -cat $file | head -1 | xxd pour le trouver ou obtenir le fichier de HDFS sur une machine locale et l'ouvrir avec vim. Il y aura un caractère tel que '^ A' dans votre vim qui est le délimiteur.

Retour à la question, vous pouvez utiliser un moyen simple pour le résoudre.

  1. Utilisez toujours INSERT OVERWRITE DIRECTORY '/user/hadoop/output' pour générer /user/hadoop/output;

  2. Créer une table externe dont les champs sont délimités par '\1':

    create external table graph_out (src string, dest string) 
    row format delimited 
    fields terminated by '\1' 
    lines terminated by '\n' 
    stored as textfile location '/user/hadoop/output';
    
4
pensz

Vous pouvez fournir un délimiteur lors de l'écriture dans des répertoires

INSERT OVERWRITE DIRECTORY '/user/hadoop/output'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY
SELECT * FROM graph_edges;

Cela devrait fonctionner pour vous.

3
user3886907

vous pouvez utiliser ce paramètre "les champs délimités par un format de ligne se terminant par '|'" par exemple, dans votre cas,

INSERT OVERWRITE DIRECTORY '/ user/hadoop/output' champs délimités par un format de ligne et terminés par '|' SELECT * FROM graph_edges;

0
Miguel Angel

Je soupçonne que Hive est en train d'écrire un contrôle-A comme séparateur, mais lorsque vous affichez un chat sur l'écran, il ne s'affiche pas à l'œil.

Au lieu de cela, essayez d’afficher le fichier dans vi ou dirigez-le si vous voulez seulement en voir un peu, et vi le résultat:

hadoop dfs -cat/user/hadoop/output/000000_0 | head> mon_local_fichier.txt

vi my_local_file.txt

Vous devriez pouvoir y voir les caractères ^ A.

0
user3267919

Ce serait une meilleure solution, je suppose, bien que ce soit un moyen de contourner le problème. 

INSERT OVERWRITE DIRECTORY '/ utilisateur/hadoop/sortie' SELECT src_node_id, '', dest_node_id FROM graph_edges;

0
bkd

J'ai eu ce problème où la sortie des résultats de la requête Hive devrait être délimitée par des tubes .. En exécutant cette commande sed, vous pouvez remplacer: ^A to |

sed 's#\x01#|#g' test.log > piped_test.log

0
user3798061

Le séparateur par défaut est "^ A" . En langage python, c'est "\ x01" .

Quand je veux changer le délimiteur, j'utilise SQL comme:

SELECT col1, délimiteur, col2, délimiteur, col3, ..., Table FROM

Ensuite, considérezdélimiteur + "^ A"comme un nouveau délimiteur.

0
moshaholo