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 constater dans les chemins répertoriés ci-dessus, l'un des noms de répertoire est un horodatage.
Problème: Je souhaite charger des fichiers d’une plage de dates allant de 20100810 à 20100813.
Je peux transmettre les paramètres «De» et «À» de la plage de dates au script Pig, mais comment puis-je 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 cela échoue lorsque j'essaie la même chose avec LOAD dans le script pig. Comment utiliser les paramètres transmis au script Pig pour charger des données à partir d'une plage de dates?
Le journal des erreurs suit:
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.access$500(JobClient.Java:170)
at org.Apache.hadoop.mapred.JobClient$2.run(JobClient.Java:793)
at org.Apache.hadoop.mapred.JobClient$2.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)
Dois-je utiliser un langage plus élevé, comme Python, pour capturer tous les horodatages de la plage et les transmettre à LOAD sous forme de liste séparée par des virgules?
à votre santé
Pig traite votre modèle de nom de fichier à l'aide des utilitaires glob de fichier hadoop, et non des utilitaires globaux du shell. Les Hadoop sont documentés ici. Comme vous pouvez le constater, hadoop ne prend pas en charge l'opérateur '..' pour une plage. Il me semble que vous avez deux options: écrire la liste {date1,date2,date2,...,dateN}
à la main, ce qui est probablement le cas, s’il s’agit d’un cas rare, ou écrire un script qui génère cette liste pour vous. Construire 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, je suis allé avec la route de liste générée, et ça fonctionne très bien (distribution CHD3).
Comme l'a dit zjffdu, le développement du chemin est réalisé par Shell. Un moyen courant de résoudre votre problème consiste à utiliser simplement les paramètres de Pig (ce qui est un bon moyen de rendre votre script encore plus lisible):
Coquille:
pig -f script.pig -param input=/user/training/test/{20100810..20100812}
script.pig:
temp = LOAD '$input' USING SomeLoader() AS (...);
j'ai rencontré cette réponse lorsque j'avais des difficultés à créer un fichier glob dans un script, puis à le transmettre en tant que paramètre dans un script pig.
aucune des réponses actuelles ne s'applique à ma situation, mais j'ai trouvé une réponse générale qui pourrait être utile ici.
dans mon cas, l'extension Shell se produisait, puis passait cela dans le script, ce qui provoquait des problèmes complets avec l'analyseur syntaxique, naturellement.
en entourant simplement le glob de guillemets doubles, il évite donc son expansion par le shell et le transmet tel quel à la commande.
NE FONCTIONNERA PAS:
$ pig -f my-pig-file.pig -p INPUTFILEMASK='/logs/file{01,02,06}.log' -p OTHERPARAM=6
MARCHERA
$ pig -f my-pig-file.pig -p INPUTFILEMASK="/logs/file{01,02,06}.log" -p OTHERPARAM=6
j'espère que cela épargnera à quelqu'un de la douleur et de l'agonie.
Donc, puisque cela fonctionne:
temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader()
mais ça ne marche pas:
temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader()
mais si vous voulez une plage de dates couvrant 300 jours, par exemple, il n'est pas élégant pour le moins de passer une liste complète à LOAD. Je suis venu avec ça et ça marche.
Supposons que vous souhaitiez charger des données du 2012-10-08 à aujourd’hui 2013-02-14, ce que vous pouvez faire est de:
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')
Merci à Dave Campbell. Une partie de la réponse ci-dessus est fausse puisqu'ils ont obtenu des votes.
Voici le résultat de mon test:
Travaux
pig -f test.pig -param input="/test_{20120713,20120714}.txt"
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 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
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, indiquez le nom du sous-dossier ou utilisez '*' pour tous les fichiers.
J'ai trouvé ce problème est causé par Linux Shell. Linux Shell vous aidera à développer
{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 à développer l'expression.
Pour répondre à Romain, si vous voulez juste paramétrer la date, le shell fonctionnera comme ceci:
pig -param input="$(echo {20100810..20100812} | tr ' ' ,)" -f script.pig
porc:
temp = LOAD '/user/training/test/{$input}' USING SomeLoader() AS (...);
S'il vous plaît noter les citations.
Dois-je utiliser un langage plus élevé, comme Python, pour capturer tous les horodatages de la plage et les transmettre à LOAD sous forme de liste séparée par des virgules?
Probablement pas - cela peut être fait en utilisant Load UDF personnalisé ou essayez de repenser votre structure de répertoires (cela fonctionnera bien si vos plages sont principalement statiques).
en outre: Pig accepte les paramètres, peut-être que cela vous aiderait (vous pourriez peut-être créer une fonction qui chargera les données d'un jour et les fusionnera dans le jeu résultant, 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 simple, il ne vous reste plus qu'à le passer à Pig, et cela devrait fonctionner correctement
Pig
statut du globe de support de hdfs
,
donc je pense que pig
peut gérer le motif /user/training/test/{20100810,20100811,20100812}
,
pourriez-vous coller les journaux d'erreur?