• Publicidad

Comparar tablas iguales

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Comparar tablas iguales

Notapor eleazaar » 2009-07-01 06:28 @311

Hola todos:

En primer lugar me gustaría agradeceros la ayuda que prestáis en este foro, porque aunque es la primera vez que posteo vengo leyéndoos desde hace tiempo.

Os cuento mi problema:

Estoy escribiendo un script (en realidad ya está escrito) para detectar similaridades entre registros, para ello tengo que comparar la tabla dónde están estos registros consigo misma. En un principio probé a crear un producto cartesiano en la consulta SQL y funcionaba bien, pero cuando la tabla es muy grande produce millones de registros que no puedo procesar por cuestiones de memoria.

Lo siguiente que intenté es hacer dos consultas separadas, de forma que el script compara cada registro de una consulta con todos los registros de la otra. Funciona a las mil maravillas, pero el problema es que es muy lento (se demora alrededor de 8 horas con 5000 registros).

Os pongo el código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
#Modulos utilizados:
use DBI;
use CONECTAR_ISI;
use TRIGRAM;

#Conectamos a la BBDD:
$dbh = Conectar->connect();

#Ejecutamos la primera consulta para extraer los campos a comparar

my $sth =
  $dbh->prepare(
"SELECT id, autor, direccion, categoria, coautores, revistas,
vid, vautor, vdireccion, vcategoria, vcoautores, vrevistas
FROM autoridades2
WHERE `vautor` NOT LIKE '%duplicado%'
ORDER BY autor ASC
"

  );
$sth->execute();
        my $sth2 =
          $dbh->prepare(
"SELECT id, autor, direccion, categoria, coautores, revistas,
vid, vautor, vdireccion, vcategoria, vcoautores, vrevistas
FROM autoridades2
WHERE `vautor` NOT LIKE '%duplicado%'
ORDER BY autor ASC
"

          );

#Convierte la consulta en un array
while (@lineas = $sth->fetchrow_array ) {

#Por cada línea encontrada en la consulta ejecutamos la siguiente para hacer
#las comparaciones

$sth2->execute();
while ( @lineas2 = $sth2->fetchrow_array() ) {

#CODIGO PARA HACER COMPARACIONES
}
}
$sth->finish();
$sth2->finish();
$dbh->disconnect();
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


He probado a poner el "$dbh2->execute()" antes del primer "while" pero entonces me devuelve un error "DBD::mysql::st fetchrow_array failed: fetch() without execute()"

A ver si podéis echarme una mano, porque yo ya no sé qué hacer para optimizarlo...
eleazaar
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2009-07-01 06:11 @299

Publicidad

Notapor explorer » 2009-07-02 06:45 @322

Bienvenido a los foros de Perl en Español, eleazaar.

Pues yo creo que el problema está justo en la comparación.

Si es simple, se podría resolver con los diccionarios (hash).

Lo primero que veo es que podrías ahorrartge las consultas mas interfnas, cacheandolas en memoria.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor eleazaar » 2009-07-02 08:19 @388

Hola explorer, muchas gracias por tu ayuda. Efectivamente el problema está en las comparaciones, que son algo complicadas, porque tengo que obtener diferentes cálculos de similaridad para los diferentes campos de cada consulta.

Probé lo que sugieres de cachear las consultas en memoria usando fetchall_array() pero pierdo una funcionalidad importante y es que si el script considera que una línea posee un equivalente más completo no quiero que vuelva a compararla, así que le inserto un "duplicado" en uno de los campos y así no vuelve a traer esa fila al hacer la siguiente consulta, pero si las cacheo en memoria pierdo esa funcionalidad, que realmente me interesa más que lo que pueda tardar en ejecutarse el script.

Aunque no perdí la esperanza de optimizar el código y esta tarde lo conseguí pasando una condición en un "if" antes de empezar a calcular las similaridades, así que sin que se alteren los resultados he conseguido pasar de casi 9 horas de ejecución a una hora y media aproximadamente. Seguramente pueda hacerse mejor, más rápido y más limpio, pero por ahora funciona ¡¡¡y en la cuarta parte de tiempo!!!

Muchas gracias de todas formas, probablemente siga preguntando cosillas, porque apenas empiezo con esto de Perl.

¡Saludos!
eleazaar
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2009-07-01 06:11 @299


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 23 invitados

cron