2012-01-03 9 views
8

Tengo que procesar algunos datos combinando dos archivos diferentes. Ambos tienen dos columnas que formarían una clave principal que puedo usar para unirlas una al lado de la otra. Los archivos en las preguntas son enormes (alrededor de 5 GB con 20 millones de filas), así que necesitaría un código eficiente. ¿Cómo haría esto en Perl?¿Cómo realizar una unión similar a SQL en Perl?

Doy un ejemplo:

Si el archivo A contiene columnas

id, name, lastname, dob, school 

Archivo B contiene columnas

address, id, postcode, dob, email 

que tendría que unirse a estos dos archivos, haciendo coincidir Identificación y dob en los dos archivos para tener un archivo de salida que tendría las columnas:

id, name, lastname, dob, school, address, postcode, email 
+1

¿Cuánta RAM tienes? –

Respuesta

8

Creo que simplemente crearía un nuevo DB mysql/sqlite/whatever e insertaría las filas. Debería haber ~ 20 líneas de perl.

Esto, por supuesto, requiere un fácil acceso a una base de datos ..

supongo que podría también ordenar los archivos por los campos interesantes y luego para cada línea en fichero1 encontrar e imprimir las líneas coincidentes en archivo2.

+1

La mayoría de las distribuciones tienen el módulo sqlite .. – shaun5

+2

...y puede construir una copia de SQLite directamente desde CPAN (DBD :: SQLite). Asegúrese de usar grandes transacciones al insertar una gran cantidad de datos en SQLite, por cierto. – tsee

0

O bien, lea detenidamente este bonito artículo Techrepublic - de todos modos es posible que necesite 5G de memoria. Me pregunto dónde utilizar las herramientas de ordenación/unión CLI de UNIX/LINUX te llevaría eficientemente. Solo un pensamiento.

2

La forma antigua de hacer esto es usar las utilidades del sistema para ordenar ambos archivos en secuencia de teclas y luego hacer coincidirlos línea por línea. Lea ambos archivos, si las claves coinciden, genere los datos. Si no coinciden, lea el archivo con la clave menor hasta que coincidan. Establezca la tecla infinitamente alta para un archivo si golpea eof. Cuando ambas teclas son infinitamente altas, has terminado.

+0

La utilidad del sistema 'join' incluso hará la unión por usted, si sus entradas están ordenadas. – reinierpost

+0

Impresionante, no lo sabía. Gracias. –

0

realidad no he probado esto, pero una solución más creativa podría ser:

  1. Lee cada archivo una vez y crear un mapa entre las combinaciones de ID + dob únicas y sus posiciones en el archivo. Use tell().
  2. crear el mapa en Perl
  3. Leer los datos reales de los archivos usando las posiciones internacional él mapa y sysread()
  4. escribir los datos en un nuevo archivo
0

También puede utilizar mi hijo de 3 años -veces módulo CPAN Set :: Relation que está diseñado para hacer cosas como esta, permitiéndote hacer todas las funciones de SQL como join en Perl. Cree un objeto Set :: Relation para cada archivo y luego use el método join(). Dicho esto, este módulo implementado mantendrá todos sus operandos y resultados en la memoria, por lo que está limitado por su RAM. Pero aún puede ver su fuente de cómo join() funciona y luego implementar una versión más eficiente para sus propósitos en función de ello.

Cuestiones relacionadas