La parte del programa que has publicado, en el primer mensaje, tiene dos partes claramente separadas: la de la consulta y la de la generación de la presentación a partir de la consulta.
De las dos partes, sería interesante ver en cuál se pierde más tiempo. Lo podrías saber con, simplemente, unos print() que sacarán el tiempo que ha tardado cada parte en realizarse.
Algo así: al principio del programa importamos el módulo
Time::HiRes:
Using perl Syntax Highlighting
use Time
::HiRes 'time';Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
y ahora ya podemos tomar mediciones de tiempo, en segundos, con precisión de milisegundos.
Vamos al código, y una línea antes de la consulta, ponemos
Using perl Syntax Highlighting
my $antes = time(); # toma el tiempo en este momento
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
y en el otro extremo, pintamos el tiempo que ha tardado en resolverse la consulta
Using perl Syntax Highlighting
print "Tiempo de la consulta (s): ", time()-$antes;
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Lo mismo podemos hacer para la parte de la representación. Obtendremos, en pantalla, el tiempo que tarda en ejecutarse cada parte (bueno, como esto es un CGI, habría que adaptarlo para que saliera de forma correcta en el HTML de la página generada o en los logs de actividad del servidor web. Para este último caso, usar warn() en lugar de print()).
Mirando con más calma la función, hay alguna cosa que se puede mejorar. Por ejemplo, parece que es muy distinto el código según tengamos un valor de $visualización u otro.
Lo que podemos hacer es sacar las distintas sentencias de bifurcación y crear una sola.
Using perl Syntax Highlighting
sub preparar
{
my $self = shift;
my $tipo = shift;
my $visualizacion = shift;
$tipo ||= 1;
## Consulta
my $antes = time();
# Personas2 es una vista de una tabla en otra BBDD,
# pero en el mismo servidor
my $personal
= $dbh->selectall_arrayref("
Select
a.id
From
Personas2 a
Where
exists (
select
1
from
atributos b
where
a.id = b.cod_atributo
and
b.ind_proc_docto = $self->{ind_proc_doc}
and
b.id_tipo_atributo = $tipo
and
b.id_dueno = $self->{dueno}
)
",
{ Slice => {} }
)
or
die $self->error($self->{dbh}->errstr)
;
warn "Tiempo de la consulta (s): ", time() - $antes;
## Formateo
$antes = time();
# Leemos el personal y arreglamos sus nombres
my @array;
foreach my $pers (@$personal) {
my $emp = new SBMP::Empleado($pers->{id});
push @array, &fixcase($emp->nombre);
}
warn "Tiempo de formateo (s): ", time() - $antes;
## Presentación
$antes = time();
if ($visualizacion) {
return
join " ; ", @array;
}
else {
print start_table({-width=>'100%'});
foreach my $pers (@array){
print
Tr(
td({-class=>"bordercell", -width=>'100%'}, $pers)
)
, "\n"
;
}
print
end_table(),
hidden('tot_pers', scalar @array)
;
}
warn "Tiempo de presentación (s): ", time() - $antes;
}
Coloreado en 0.003 segundos, usando
GeSHi 1.0.8.4
(Nota: que se pueda escribir, o no, la consulta SQL de esta manera, en varias líneas, depende del motor de base de datos que estemos usando).
Como ves, hemos simplificado mucho el código, dejando solo una sentencia condicional.
Por otra parte, aunque no soy nada experto en SQL, estoy sospechando que la consulta se puede simplificar en:
Using sql Syntax Highlighting
SELECT
a
.id
FROM
Personas2 a
, atributos b
WHERE
a
.id
= b
.cod_atributo
AND
b
.ind_proc_docto
= $self
->{ind_proc_doc
}
AND
b
.id_tipo_atributo
= $tipo
AND
b
.id_dueno
= $self
->{dueno
}Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Y, finalmente, de la creación de los objetos SBMP::Empleado, me parece que puede simplificarse esas consultas, si obtenemos los nombres de las personas por adelantado.
O, si sabemos que hay muchas repeticiones en la obtención de esos datos, usar el módulo
Memoize con esa función.
En fin, que posibilidades hay muchas. Pero si aún así, el responsable es Perl, habrá que pensar que el problema está en el controlador que dialoga con la base de datos.