2010-08-18 13 views
28

Tengo el siguiente de escenariosPig Latin: Cargar múltiples archivos de un intervalo de fechas (parte de la estructura de directorios)

versión cerdo utiliza 0,70

Muestra estructura de directorios 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> 

Como puede ver en las rutas enumeradas anteriormente, uno de los nombres de directorio es un sello de fecha.

Problema: quiero cargar archivos desde un intervalo de fechas decir de 20.100.810 a 20100813.

puedo pasar el 'de' y 'a' del intervalo de fechas como parámetros al script de cerdo sino cómo Cómo hago uso de estos parámetros en la instrucción LOAD? Soy capaz de realizar las siguientes

temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader() AS (...); 

las siguientes obras con Hadoop:

hadoop fs -ls /user/training/test/{20100810..20100813} 

pero fracasa al intentar lo mismo con CARGA dentro de la secuencia de comandos de cerdo. ¿Cómo hago uso de los parámetros pasados ​​al script Pig para cargar datos de un rango de fechas?

registro de error siguiente:

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) 

¿Es necesario hacer uso de un lenguaje de alto como Python para capturar todas las marcas de fecha en el rango y pasarlos para cargar como una lista separada por comas?

aplausos

+0

Para las personas que encontraron esta publicación al buscar [ERROR 1066: no se puede abrir el iterador para el alias] (http://stackoverflow.com/questions/34495085/error-1066-unable-to-open-iterator-for- alias-in-pig-generic-solution) aquí hay una [solución genérica] (http://stackoverflow.com/a/34495086/983722). –

Respuesta

19

Pig está procesando su patrón de nombre de archivo utilizando las utilidades globales de archivo hadoop, no las utilidades globales de shell. Hadoop están documentados here. Como puede ver, hadoop no admite el operador '..' para un rango. Me parece que tiene dos opciones: escribir la lista {date1,date2,date2,...,dateN} a mano, que si se trata de un caso de uso raro es probablemente el camino a seguir o escribir un script de contenedor que genere esa lista para usted. La creación de dicha lista a partir de un rango de fechas debe ser una tarea trivial para el lenguaje de scripts de su elección. Para mi aplicación, me he ido con la ruta de la lista generada, y está funcionando bien (distribución CHD3).

+2

actualización de enlace http://hadoop.apache.org/docs/stable/api/org/apache/hadoop/fs/FileSystem.html#globStatus%28org.apache.hadoop.fs.Path – BozoJoe

1

¿Es necesario hacer uso de un lenguaje de alto como Python para capturar todas las marcas de fecha en el rango y pasarlas para cargar como una lista separada por comas?

Probablemente no - esto se puede hacer utilizando la costumbre de carga UDF, o intenta que repensar la estructura de directorios (esto funciona bien si sus rangos son en su mayoría estáticos).

además: Cerdo acepta parámetros, tal vez esto le ayudaría (tal vez usted podría hacer la función que va a cargar los datos de un día y la unión al conjunto resultante, pero no sé si es posible)

edición : probablemente escrito pitón simple o escritura del golpe que genera lista de fechas (carpetas) es la solución más fácil, que no sólo tienen que pasar a cerdo, y esto debería funcionar bien

+0

Gracias Wojtek.Bueno, la grilla ya está en su lugar y no es factible cambiar la estructura del directorio. Veo eso, temp = LOAD '/ user/training/test/{20100810,20100811,20100812}' USANDO SomeLoader() AS (...); y hadoop fs -ls/user/training/test/{20100810,20100811,20100812} funciona bien. hadoop fs -ls /user/training/test/{20100810..20100812} también funciona pero temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader() AS (...); falla al volcar la temperatura o almacenar la temperatura. – Arnkrishn

0

Pig apoyo globo estado de hdfs,

así que creo que pig puede manejar th patrón e /user/training/test/{20100810,20100811,20100812},

podría pegar los registros de errores?

+0

Hola zjffdu, he copiado el registro de errores en la pregunta. Gracias – Arnkrishn

4

Encontré este problema debido al shell de linux.shell de Linux le ayudará a ampliar

{20100810..20100812} 

a

20100810 20100811 20100812, 

entonces en realidad se ejecuta el comando

bin/hadoop fs -ls 20100810 20100811 20100812 

Pero en el hdfs api, no va a ayudar a expandir la expresión.

30

Como dijo zjffdu, la expansión de la ruta la realiza el shell. Una forma común de resolver su problema es simplemente usar parámetros de cerdo (que es una buena manera de hacer que su guión más resuable de todos modos):

shell:

pig -f script.pig -param input=/user/training/test/{20100810..20100812} 

script.pig:

temp = LOAD '$input' USING SomeLoader() AS (...); 
+0

Funciona como un encanto para mí. – minhas23

+1

Esto no funciona en absoluto, pero puede parecer que funciona porque pig tiene un manejo de línea de comandos espantoso. Estás utilizando bash para generar una línea de comando que invocará al cerdo. Pero se expande a 'pig -f script.pig -param input =/user/training/test/20100810 input =/user/training/test/20100811 input =/user/training/test/20100812' (cambia el' pig' para 'eco' si quieres verlo). Solo el primer 'input =' es precedido por '-param'; el resto no son enlaces de parámetros de cerdo en absoluto. ¡Pero cerdo simplemente deja de procesar los argumentos de la línea de comando en la primera entrada no reconocida = ... 'y ejecuta solo la primera fecha! – Ben

+1

Puede probar que el cerdo está ignorando todo después de la segunda 'entrada = ...' utilizando un script de cerdo con un segundo parámetro (digamos 'output'), y poniendo el' -param output = ... 'después del enlace de entrada . Obtiene un error sobre 'Parámetro no definido: salida'. – Ben

4
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 está en el medio de la ruta de archivo, nombre de la subcarpeta concate o uso '*' para todos los archivos.

9

me encontré con esta respuesta cuando tenía problemas para tratar de crear un archivo glob en un script y luego pasarlo como un parámetro en un script de cerdo.

Ninguna de las respuestas actuales se aplicó a mi situación, pero encontré una respuesta general que podría ser útil aquí.

en mi caso, la expansión del shell estaba pasando y luego pasando eso al script - causando problemas completos con el analizador de cerdos, comprensiblemente.

por lo que simplemente rodeando el globo en comillas dobles lo protege de ser expandido por el caparazón, y lo pasa como está en el comando.

no funcionará:

$ pig -f my-pig-file.pig -p INPUTFILEMASK='/logs/file{01,02,06}.log' -p OTHERPARAM=6 

trabajará

$ pig -f my-pig-file.pig -p INPUTFILEMASK="/logs/file{01,02,06}.log" -p OTHERPARAM=6 

espero que esto ahorra a alguien algo de dolor y agonía.

4

Gracias a dave campbell. Algunas de las respuestas más allá están mal ya que obtuvieron algunos votos.

A continuación se presenta el resultado de mi prueba:

  • trabajo

    • cerdo -f test.pig -param entrada = "/ test_ {} 20120713,20120714 .txt"
      • No se puede tener espacio antes o después de "," en la expresión
    • pig -f test.pig -param input = "/ test_ 201207 * .txt"
    • cerdo -f test.pig -param entrada = "/ test_2012071? .txt"
    • cerdo -f test.pig -param entrada = "/ test_20120713.txt,/test_20120714.txt"
    • cerdo -f test.pig -param entrada =/test_20120713.txt,/test_20120714.txt
      • no se puede tener un espacio antes o después "" en la expresión
  • no hacer Trabajo

    • cerdo -f test.pig -param de entrada = "/ test_ {20120713..20120714} .txt"
    • cerdo -f test.pig -param entrada =/test_ {20120713,20120714} .txt
    • cerdo -f test.pig -param entrada =/test_ {} 20120713..20120714 .txt
6

Así que ya que esto funciona:

temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader() 

pero esto no funciona:

temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader() 

pero si quieres un rango de fechas que dure 300 días y pasar una lista completa a LOAD no es elegante, por decir lo menos. Se me ocurrió esto y funciona.

decir que quiere cargar datos desde 10/08/2012 a 02/14/2013 hoy, lo que puede hacer es

temp = LOAD '/user/training/test/{201210*,201211*,201212,2013*}' USING SomeLoader() 

luego hacer un filtro después de que

filtered = FILTER temp BY (the_date>='2012-10-08') 
+0

Es una buena solución para manejar tales escenarios – minhas23

+0

la sintaxis de comodín entre paréntesis, por ejemplo "/ test/{201210 *, 201211 *}" es muy eficiente y fácil de implementar – Quetzalcoatl

1

Para la respuesta de Romain, si quieres simplemente parametrizar la fecha, la cáscara se ejecutará la siguiente manera:

pig -param input="$(echo {20100810..20100812} | tr ' ' ,)" -f script.pig 

cerdo:

temp = LOAD '/user/training/test/{$input}' USING SomeLoader() AS (...); 

Tenga en cuenta las cotizaciones.

Cuestiones relacionadas