Pig Latin: charger plusieurs fichiers à partir d'une plage de dates (fait partie de la structure du répertoire)
j'ai le scénario suivant -
version porcine utilisée 0.70
exemple de structure de répertoire HDFS:
/user/training/test/20100810/<data files>
/user/training/test/20100811/<data files>
/user/training/test/20100812/<data files>
/user/training/test/20100813/<data files>
/user/training/test/20100814/<data files>
comme vous pouvez le voir dans les chemins énumérés ci-dessus, l'un des noms de répertoire est un tampon de date.
problème: je veux charger des fichiers à partir d'une date comprise entre 20100810 et 20100813.
je peux passer le " de " et " à " de la plage de dates paramètres du script Pig mais comment utiliser ces paramètres dans L'instruction LOAD. Je suis capable de faire ce qui suit
temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader() AS (...);
les œuvres suivantes avec hadoop:
hadoop fs -ls /user/training/test/{20100810..20100813}
mais il échoue quand J'essaie la même chose avec LOAD à l'intérieur du script pig. Comment puis-je utiliser les paramètres passés au script Pig pour charger des données à partir d'une plage de dates?
journal des erreurs:
Backend error message during job submission
-------------------------------------------
org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigInputFormat.getSplits(PigInputFormat.java:269)
at org.apache.hadoop.mapred.JobClient.writeNewSplits(JobClient.java:858)
at org.apache.hadoop.mapred.JobClient.writeSplits(JobClient.java:875)
at org.apache.hadoop.mapred.JobClient.access0(JobClient.java:170)
at org.apache.hadoop.mapred.JobClient.run(JobClient.java:793)
at org.apache.hadoop.mapred.JobClient.run(JobClient.java:752)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1062)
at org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:752)
at org.apache.hadoop.mapred.JobClient.submitJob(JobClient.java:726)
at org.apache.hadoop.mapred.jobcontrol.Job.submit(Job.java:378)
at org.apache.hadoop.mapred.jobcontrol.JobControl.startReadyJobs(JobControl.java:247)
at org.apache.hadoop.mapred.jobcontrol.JobControl.run(JobControl.java:279)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input Pattern hdfs://<ServerName>.com/user/training/test/{20100810..20100813} matches 0 files
at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:231)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigTextInputFormat.listStatus(PigTextInputFormat.java:36)
at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.getSplits(FileInputFormat.java:248)
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigInputFormat.getSplits(PigInputFormat.java:258)
... 14 more
Pig Stack Trace
---------------
ERROR 2997: Unable to recreate exception from backend error: org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}
org.apache.pig.impl.logicalLayer.FrontendException: ERROR 1066: Unable to open iterator for alias test
at org.apache.pig.PigServer.openIterator(PigServer.java:521)
at org.apache.pig.tools.grunt.GruntParser.processDump(GruntParser.java:544)
at org.apache.pig.tools.pigscript.parser.PigScriptParser.parse(PigScriptParser.java:241)
at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:162)
at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:138)
at org.apache.pig.tools.grunt.Grunt.run(Grunt.java:75)
at org.apache.pig.Main.main(Main.java:357)
Caused by: org.apache.pig.backend.executionengine.ExecException: ERROR 2997: Unable to recreate exception from backend error: org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}
at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.Launcher.getStats(Launcher.java:169)
ai-je besoin utiliser un langage supérieur comme Python pour capturer tous les datations dans la gamme et les passer pour les charger en tant que liste séparée par des virgules?
cheers
10 réponses
Pig traite votre motif de nom de fichier en utilisant le fichier hadoop glob utilities, pas les utilitaires glob de l'interpréteur de commandes. Hadoop sont documentées ici . Comme vous pouvez le voir, hadoop ne soutient pas le"..'opérateur pour une gamme. Il me semble que vous avez deux options - soit écrire le {date1,date2,date2,...,dateN}
liste à la main, si c'est un rare cas d'utilisation est probablement la voie à suivre, ou d'écrire un script qui génère cette liste pour vous. Bâtiment une telle liste à partir d'une plage de dates devrait être une tâche triviale pour le langage de script de votre choix. Pour mon application, j'ai suivi la route de liste générée, et ça marche très bien (distribution CHD3).
comme disait zjffdu, l'expansion du chemin est faite par le shell. Une façon courante de résoudre votre problème est d'utiliser simplement des paramètres Pig (ce qui est une bonne façon de rendre votre script plus valable de toute façon):
coquille:
pig -f script.pig -param input=/user/training/test/{20100810..20100812}
"151920920 de script".porc:
temp = LOAD '$input' USING SomeLoader() AS (...);
j'ai couru à travers cette réponse quand j'avais de la difficulté à créer un dossier glob dans un script et puis le passer comme un paramètre dans un script de cochon.
aucune des réponses actuelles ne s'appliquait à ma situation, mais j'ai trouvé une réponse générale qui pourrait être utile ici.
dans mon cas, l'expansion de la coque se produisait et ensuite le passer dans le script - causant des problèmes complets avec l'analyseur de porcs, naturellement.
ainsi, en entourant simplement la glob en guillemets doubles la protège d'être étendue par le shell, et la passe comme est dans la commande.
NE FONCTIONNE PAS:
$ pig -f my-pig-file.pig -p INPUTFILEMASK='/logs/file{01,02,06}.log' -p OTHERPARAM=6
FONCTIONNERA
$ pig -f my-pig-file.pig -p INPUTFILEMASK="/logs/file{01,02,06}.log" -p OTHERPARAM=6
j'espère que cela sauve quelqu'un de la douleur et d'agonie.
donc puisque cela fonctionne:
temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader()
mais cela ne fonctionne pas:
temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader()
mais si vous voulez un intervalle de date qui s'étend disons 300 jours et passer une liste complète à charger n'est pas élégant pour dire le moins. Je suis venu avec et ça marche.
dites que vous voulez charger des données de 2012-10-08 à aujourd'hui 2013-02-14, ce que vous pouvez faire est
temp = LOAD '/user/training/test/{201210*,201211*,201212,2013*}' USING SomeLoader()
puis faire un filtre après cela
filtered = FILTER temp BY (the_date>='2012-10-08')
temp = LOAD '/user/training/test/2010081*/*' USING SomeLoader() AS (...);
load 20100810~20100819 data
temp = LOAD '/user/training/test/2010081{0,1,2}/*' USING SomeLoader() AS (...);
load 20100810~2010812 data
si la variable se trouve au milieu du chemin du fichier, concater le nom du sous-dossier ou utiliser '*' pour tous les fichiers.
j'ai trouvé que ce problème est causé par Linux shell. Linux shell vous aidera à étendre
{20100810..20100812}
à
20100810 20100811 20100812,
alors vous exécutez réellement la commande
bin/hadoop fs -ls 20100810 20100811 20100812
mais dans le hdfs api
, cela ne vous aidera pas à étendre l'expression.
merci à dave campbell. Une partie de la réponse au-delà sont faux puisqu'ils ont obtenu quelques votes.
voici le résultat de mon test:
-
Œuvres
-
pig -f test.pig -param input="/test_{20120713,20120714}.txt"
- Ne peut pas avoir d'espace avant ou après "," dans l'expression
-
pig -f test.pig -param input="/test_201207*.txt"
-
pig -f test.pig -param input="/test_2012071?.txt"
-
pig -f test.pig -param input="/test_20120713.txt,/test_20120714.txt"
-
pig -f test.pig -param input=/test_20120713.txt,/test_20120714.txt
- Ne peut pas avoir d'espace avant ou après "," dans l'expression
-
-
Ne fonctionne pas
-
pig -f test.pig -param input="/test_{20120713..20120714}.txt"
-
pig -f test.pig -param input=/test_{20120713,20120714}.txt
-
pig -f test.pig -param input=/test_{20120713..20120714}.txt
-
dois-je utiliser un langage supérieur comme Python pour capturer tous les datations dans la gamme et les passer pour les charger en tant que liste séparée par des virgules?
probablement vous ne le faites pas - cela peut être fait en utilisant UDF de charge personnalisé, ou essayez de repenser votre structure de répertoire (cela fonctionnera bien si vos gammes sont la plupart du temps statiques).
en outre: le cochon accepte les paramètres, peut - être que cela vous aiderait (peut-être que vous pourriez faire fonction qui vous permettra de charger des données à partir d'un jour et de l'union de jeu, mais je ne sais pas si c'est possible)
edit: probablement écrire un simple script python ou bash qui génère une liste de dates (dossiers) est la solution la plus facile, vous avez juste à le passer à Pig, et cela devrait fonctionner très bien
pour la réponse de Romain, si vous voulez simplement paramétrer la date, le shell tournera comme ceci:
pig -param input="$(echo {20100810..20100812} | tr ' ' ,)" -f script.pig
cochon:
temp = LOAD '/user/training/test/{$input}' USING SomeLoader() AS (...);
veuillez noter les guillemets.
Pig
soutien globe statut de hdfs
,
donc je pense que pig
peut supporter le motif
/user/training/test/{20100810,20100811,20100812}
,
pourrait vous coller les journaux d'erreur ?