El 17/05/13 15:39, Alvaro Herrera escribió:
Francisco Javier Morosini Eguren escribió:
Alvaro, el usar un right join vs un with tiene alguna diferencia en
performance ? o es transparente?
Bueno, son cosas sin relación. Lo que pongas en el WITH va a ser
equivalente a un elemento más del FROM. Es decir, en teoría podrías
agregar el CTE ("common table elemento", que es una pseudo-tabla que
defines en el WITH) dentro del FROM como un subselect. Tanto al CTE
como al subselect le puedes hacer JOINs de todo tipo. Ahora, si la
pregunta es "un CTE, ¿cómo se compara con un elemento del FROM?",
entonces la respuesta es que cada CTE siempre se optimiza separadamente
del resto de la consulta; para conseguir un resultado equivalente en el
subselect tendrías que agregarle OFFSET 0, que actúa como "barrera de
optimización".
En otras palabras, si puedes usar un outer join (right o left) evitando
el WITH, seguramente será mejor porque se puede optimizar en conjunto
con el resto de la consulta. La gracia del WITH (además de poder usarse
en consultas recursivas) es que la consulta suele ser más legible.
Hola a todos, a parte de que WITH poder usarse en consultas recursivas y
que de sea más legible, acá la hemos utilizado para mejorar el tiempo de
respuesta de consultas que tienen una subconsulta en el los atributos
que devuelve.
por ejemplo:
empid, dpto,salario,edad, promedio de su dpto
--esto se puede resolver con ventanas
( SELECT empid, departamento, salario, edad,
avg(salario) OVER (PARTITION BY departamento)
AS salario_medio FROM empleado)
Y mejora cantidad, pero con WITH también
la consulta sola queda +- así:
SELECT
e1.empid,
e1.departamento, e1.salario, e1.edad, (select
avg(e2.salario) from empleado e2 where
e2.departamento=e1.departamento)
as
promedio FROM empleado e1;
explain analyze:
"Seq Scan on empleado e1 (cost=0.00..493482.00 rows=5000 width=22)
(actual time=2.564..11494.733 rows=5000 loops=1)"
" SubPlan 1"
" -> Aggregate (cost=98.67..98.68 rows=1 width=4) (actual
time=2.295..2.295 rows=1 loops=5000)"
" -> Seq Scan on empleado e2 (cost=0.00..94.50 rows=1667
width=4) (actual time=0.007..1.555 rows=1667 loops=5000)"
" Filter: (departamento = e1.departamento)"
"Total runtime: 11497.291 ms"
Con WITH mejora considerablemente también :D
WITH departamento_salario as
(SELECT e2.departamento, AVG(e2.salario)
as salario_promedio FROM empleado e2
GROUP BY departamento)
SELECT
e1.empid,
e1.departamento,
e1.salario,
e1.edad,
departamento_salario.salario_promedio
FROM empleado e1, departamento_salario
WHERE departamento_salario.departamento
= e1.departamento;
explain analyze:
"Hash Join (cost=107.13..257.88 rows=5000 width=54) (actual
time=5.812..13.573 rows=5000 loops=1)"
" Hash Cond: (e1.departamento = departamento_salario.departamento)"
" CTE departamento_salario"
" -> HashAggregate (cost=107.00..107.04 rows=3 width=14) (actual
time=5.764..5.768 rows=3 loops=1)"
" -> Seq Scan on empleado e2 (cost=0.00..82.00 rows=5000
width=14) (actual time=0.005..2.182 rows=5000 loops=1)"
" -> Seq Scan on empleado e1 (cost=0.00..82.00 rows=5000 width=22)
(actual time=0.014..2.279 rows=5000 loops=1)"
" -> Hash (cost=0.06..0.06 rows=3 width=64) (actual time=5.783..5.783
rows=3 loops=1)"
" Buckets: 1024 Batches: 1 Memory Usage: 1kB"
" -> CTE Scan on departamento_salario (cost=0.00..0.06 rows=3
width=64) (actual time=5.770..5.777 rows=3 loops=1)"
"Total runtime: 15.337 ms"
saludos
http://www.uci.cu
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda@postgresql.org)
Para cambiar tu suscripción:
http://www.postgresql.org/mailpref/pgsql-es-ayuda