Re: Optimizar query

From: Miguel Juliÿffffe1n de la Fuente <jmdelafuente(at)yahoo(dot)com(dot)ar>
To: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Optimizar query
Date: 2006-07-24 16:39:56
Message-ID: 20060724163956.62032.qmail@web52611.mail.yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Muestro el EXPLAIN ANALYZE, desde ya muchas gracias.

EXPLAIN ANALYZE
SELECT the_geom, nombre FROM
shortest_path('SELECT id, source, target, cost FROM calles_tmp_edges where partido=45', 6001, 9960, false, false) a
inner join calles_tmp b
inner join calles_nombre n
on b.idcalle=n.idcalle
on a.edge_id=b.edge_id
where partido=45

"Merge Join (cost=2061.75..2721.72 rows=43665 width=77) (actual time=1950.551..1991.743 rows=49 loops=1)"
" Merge Cond: ("outer".edge_id = "inner".edge_id)"
" -> Sort (cost=62.33..64.83 rows=1000 width=4) (actual time=473.271..473.360 rows=50 loops=1)"
" Sort Key: a.edge_id"
" -> Function Scan on shortest_path a (cost=0.00..12.50 rows=1000 width=4) (actual time=472.492..472.652 rows=50 loops=1)"
" -> Sort (cost=1999.42..2021.25 rows=8733 width=81) (actual time=1420.252..1480.678 rows=14692 loops=1)"
" Sort Key: b.edge_id"
" -> Hash Join (cost=63.63..1427.74 rows=8733 width=81) (actual time=145.128..733.827 rows=23287 loops=1)"
" Hash Cond: ("outer".idcalle = "inner".idcalle)"
" -> Seq Scan on calles_tmp b (cost=0.00..1223.19 rows=10719 width=72) (actual time=37.283..417.470 rows=29223 loops=1)"
" -> Hash (cost=61.30..61.30 rows=932 width=17) (actual time=17.250..17.250 rows=0 loops=1)"
" -> Seq Scan on calles_nombre n (cost=0.00..61.30 rows=932 width=17) (actual time=5.235..13.832 rows=932 loops=1)"
" Filter: (partido = 45)"
"Total runtime: 1998.597 ms"

EXPLAIN ANALYZE
SELECT the_geom, nombre FROM
shortest_path('SELECT id, source, target, cost FROM calles_tmp_edges where partido=45', 6001, 9960, false, false) a
inner join calles_tmp b
inner join calles_nombre n
on b.idcalle=n.idcalle
on a.edge_id=b.edge_id
where partido=45

"Nested Loop (cost=13.50..236376.67 rows=43665 width=77) (actual time=1944.100..7761.394 rows=49 loops=1)"
" Join Filter: ("inner".edge_id = "outer".edge_id)"
" -> Nested Loop (cost=0.00..39870.67 rows=8733 width=81) (actual time=405.498..2457.878 rows=23287 loops=1)"
" -> Index Scan using calles_tmp_id_calle_idq on calles_tmp b (cost=0.00..7039.83 rows=10719 width=72) (actual time=0.495..632.118 rows=29223 loops=1)"
" -> Index Scan using ix_idcalle on calles_nombre n (cost=0.00..3.05 rows=1 width=17) (actual time=0.037..0.044 rows=1 loops=29223)"
" Index Cond: ("outer".idcalle = n.idcalle)"
" Filter: (partido = 45)"
" -> Materialize (cost=13.50..23.50 rows=1000 width=4) (actual time=0.021..0.092 rows=50 loops=23287)"
" -> Function Scan on shortest_path a (cost=0.00..12.50 rows=1000 width=4) (actual time=441.421..441.586 rows=50 loops=1)"
"Total runtime: 7761.931 ms"




Miguel Juliÿffffe1n de la Fuente <jmdelafuente(at)yahoo(dot)com(dot)ar> escribió:
Hola lista, tengo instalado "PostgreSQL 8.0.1 on i686-pc-linux-gnu, compiled by GCC 2.95.4" sobre debian, estoy tratando de ejecutar un consulta que sobre el resultado de una funcion (shortest_path devuelve aprox. 50 filas) debe unir otra tabla (calles_tmp de 30000 filas) a traves de un campo indizado en esta tabla y a su vez con otro campo de esta segunda tabla unir una tercera (calles_nombre de 1100 filas) que tambien dispone de indice por el campo buscado:

si yo ejecuto lo siguiente:

SELECT the_geom, nombre
FROM
shortest_path('SELECT id, source, target, cost FROM calles_tmp_edges where partido=45', 6001, 9960, false, false) a
inner join calles_tmp b
inner join calles_nombre n
on b.idcalle=n.idcalle
on a.edge_id=b.edge_id
where partido=45

el plan de ejecucion resulta

Merge Join (cost=2061.75..2721.72 rows=43665 width=77)
Merge Cond: ("outer".edge_id = "inner".edge_id)
-> Sort (cost=62.33..64.83 rows=1000 width=4)
Sort Key: a.edge_id
-> Function Scan on shortest_path a (cost=0.00..12.50 rows=1000 width=4)
-> Sort (cost=1999.42..2021.25 rows=8733 width=81)
Sort Key: b.edge_id
-> Hash Join (cost=63.63..1427.74 rows=8733 width=81)
Hash Cond: ("outer".idcalle = "inner".idcalle)
-> Seq Scan on calles_tmp b (cost=0.00..1223.19 rows=10719 width=72)
-> Hash (cost=61.30..61.30 rows=932 width=17)
-> Seq Scan on calles_nombre n (cost=0.00..61.30 rows=932 width=17)
Filter: (partido = 45)

que demora mas de 2 segundos y no parece ser el camino optimo.

Por esta razon tratamos de optimizarlos forzando a un nested loop de la siguiente manera:

set enable_seqscan=off; set enable_mergejoin=off; set enable_hashjoin=off; set enable_nestloop=on;

esperando que buscara a partir del resultado de la funcion las coincidencias en calles_tmp y luego a partir de este nuevo resultado las coincidencias en calles_nombre.

Pero, no. Utiliza los nested loops, pero no en el orden correcto. Primero une calles_tmp con calles_nombres y luego une el resultado de la funcion, tardando 8 segundos.
Copio el plan de ejecucion:

Nested Loop (cost=13.50..236376.67 rows=43665 width=77)
Join Filter: ("inner".edge_id = "outer".edge_id)
-> Nested Loop (cost=0.00..39870.67 rows=8733 width=81)
-> Index Scan using calles_tmp_id_calle_idq on calles_tmp b (cost=0.00..7039.83 rows=10719 width=72)
-> Index Scan using ix_idcalle on calles_nombre n (cost=0.00..3.05 rows=1 width=17)
Index Cond: ("outer".idcalle = n.idcalle)
Filter: (partido = 45)
-> Materialize (cost=13.50..23.50 rows=1000 width=4)
-> Function Scan on shortest_path a (cost=0.00..12.50 rows=1000 width=4)

Finalmente, para forzar el orden de ejecucion de las consultas, no se nos ocurrio mas que dividir las consultas guardando el resultado del primer join en una tabla temporal y luego ejecutando el segundo join.

select the_geom, idcalle
into temporary pp
from shortest_path('SELECT id, source, target, cost FROM calles_tmp_edges where partido=45', 6001, 9960, false, false) a
inner join calles_tmp b on a.edge_id=b.edge_id;

SELECT the_geom, nombre FROM pp b
inner join calles_nombre n
on b.idcalle=n.idcalle
where partido=45;

Asi, el tiempo se redujo a 640 ms.

Mis dudas son:
-- no hay alguna forma mas "elegante" de resolver el problema??
-- No le puedo indicar el orden en que debe realizar los join de alguna otra manera??
-- Y, aunque no sea mi caso, no le puedo indicar la forma de union individualmente (lo que en otro DBMS seria "inner loop join") ??

Espero sus respuestas. Muchas gracias.

---------------------------------
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
Probalo ya!


---------------------------------
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
Probalo ya!

In response to

  • Optimizar query at 2006-07-24 15:42:26 from Miguel Juliÿffffe1n de la Fuente

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Paulina Quezada 2006-07-24 16:48:52 Crear vistas desde otra base de datos...
Previous Message Alvaro Herrera 2006-07-24 16:18:03 Re: Optimizar query