Jump to content


Photo

[RESUELTO] Sobre consulta sql


  • Please log in to reply
20 replies to this topic

#1 look

look

    Advanced Member

  • Miembros
  • PipPipPip
  • 418 posts
  • LocationLa Ceiba-Atlantida-Honduras

Posted 07 September 2011 - 11:28 AM

hola amigos, ¿cual de estas consultas es mejor y porque?
las dos consultas muestran el mismo resultado, es decir funcionan bien.


select a.refer,b.descr,a.almacen,a.fecha_docu
from minv01 a , conm01 b
where b.num_cpto = a.tipo_mov



select a.refer,b.descr,a.almacen,a.fecha_docu
from minv01 a
join conm01 b on b.num_cpto = a.tipo_mov


saludos!!!
  • 0

#2 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 07 September 2011 - 11:41 AM

hola amigos, ¿cual de estas consultas es mejor y porque?
las dos consultas muestran el mismo resultado, es decir funcionan bien.


select a.refer,b.descr,a.almacen,a.fecha_docu
from minv01 a , conm01 b
where b.num_cpto = a.tipo_mov



select a.refer,b.descr,a.almacen,a.fecha_docu
from minv01 a
join conm01 b on b.num_cpto = a.tipo_mov


saludos!!!


En realidad ambas consultas son iguales. Si revisas el plan de ejecución de ambas te darán por resultado un mismo rendimiento
  • 0

#3 look

look

    Advanced Member

  • Miembros
  • PipPipPip
  • 418 posts
  • LocationLa Ceiba-Atlantida-Honduras

Posted 07 September 2011 - 11:53 AM

creo que esa era mi duda, el rendimiento de la consulta.
  • 0

#4 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 07 September 2011 - 12:00 PM

creo que esa era mi duda, el rendimiento de la consulta.


Me tome la libertad de simular tu consulta y generar el plan de ejecución en sql server.

Aquí el resultado:

Imagen Enviada
comparativa por poliburro, en Flickr
  • 0

#5 TiammatMX

TiammatMX

    Advanced Member

  • Miembros
  • PipPipPip
  • 1750 posts
  • LocationUniverso Curvo\Vía Láctea\Sistema Solar\Planeta Tierra\América\México\Ciudad de México\Xochimilco\San Gregorio Atlapulco\Home

Posted 07 September 2011 - 12:07 PM

...


select a.refer,b.descr,a.almacen,a.fecha_docu
from minv01 a
join conm01 b on b.num_cpto = a.tipo_mov

...


Si fuera concurso de "elegancia" del código, votaría sin duda por ésta.
  • 0

#6 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 07 September 2011 - 12:24 PM

creo que esa era mi duda, el rendimiento de la consulta.


Bueno, una de las primeras cosas al considerar mejorar el rendimiento de nuestras bases de datos es el crear los índices necesarios en nuestras tablas, y para esta tarea están las herramientas de analisis de plan de ejecución.

En este caso, tu primer consulta contiene lo que se define (si mi memoria no me falla) en el estandard de Ansi Sql/86  como Join natural, para el estandard ansi sql/92 se estila la segunda.

Saludox

  • 0

#7 look

look

    Advanced Member

  • Miembros
  • PipPipPip
  • 418 posts
  • LocationLa Ceiba-Atlantida-Honduras

Posted 07 September 2011 - 01:02 PM

hola, gracias amigo Poli. aclaraste mi duda...

Saludos!!!

  • 0

#8 felipe

felipe

    Advanced Member

  • Administrador
  • 3283 posts
  • LocationColombia

Posted 07 September 2011 - 01:14 PM

¿Fuera de eso es por la integridad no?


Saludos!
  • 0

#9 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 07 September 2011 - 01:20 PM

¿Fuera de eso es por la integridad no?


Saludos!



mmm, cre que no entendí la pregunta amigo.
  • 0

#10 felipe

felipe

    Advanced Member

  • Administrador
  • 3283 posts
  • LocationColombia

Posted 07 September 2011 - 02:38 PM


¿Fuera de eso es por la integridad no?


Saludos!



mmm, cre que no entendí la pregunta amigo.


Me refiero a que también va ligado al tema de las relaciones entre tablas, puesto que en el primer caso no es tan necesario.


Saludos!
  • 0

#11 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 07 September 2011 - 03:13 PM

Mmmm, claro amigo felipe, las relaciones son un tema muy importante a la hora de diseñar nuestro modelo de base de datos
  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6295 posts
  • LocationArgentina

Posted 08 September 2011 - 05:52 PM

Hola,
Disculpen que me meta de aguafiestas pero tengo entendido que en realidad no es lo mismo hacer un:


where TablaA.Campo1 = TablaB.Campo1



que el aplicar un join:



join TablaB
on TablaA.Campo1 = TablaB.Campo1



Sobre todo cuando se trata de valores NULLs.  ;)


Cuando se utiliza JOINs, según el estándar, el motor obvia aquellos registros que tengan en sus campos comunales el NULL (a menos se que utilice LEFT|RIGTH [OUTER]). Mientras que al utilizar el where no considera una evaluación en los campos comunes. Más bien obvia aquellos en los que una de las partes sea NULL. Que no es lo mismo.


Si obtienes los mismos resultados, es nada más por una simple coincidencia. Pero prueba poniendo campos NULL tanto en A como en B con ambas consultas. Deberías obtener "lijeras" diferencias. Eso dice la teoría.


Ahora bien... si debo aclarar algunas cuestiones respecto a la práctica: algunos motores asumen un where del tipo:


TablaA.Campo1 = TablaB.Campo1



como un join implícito (como por ejemplo, Firebird) y convierten a esa condición en un join. Eso hace, y explica, el porqué se obtiene el mismo resultado.


Hay consultas en las que se puede esperar el uso del where, mientras que hay otras en las que obligadamente se debe hacer uso de un join. De cualquier forma el join es el método más seguro y está mejor preparado y optimizado por todos los motores para hacer una coincidencia entre dos campos de dos tablas.
Por seguridad y estabilidad, prímese el uso de JOIN; sobre todo los explícitos.


Saludos,
  • 0

#13 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 08 September 2011 - 10:47 PM

Hola,
Disculpen que me meta de aguafiestas pero tengo entendido que en realidad no es lo mismo hacer un:


where TablaA.Campo1 = TablaB.Campo1



que el aplicar un join:



join TablaB
on TablaA.Campo1 = TablaB.Campo1



Sobre todo cuando se trata de valores NULLs. 


:p jojojo difiero amigo, pues en esta situación ambas consultas hacen lo mismo, descartan las claves no coincidentes y por tanto nunca aparecen nulos del lado derecho o izquierdo
  • 0

#14 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 09 September 2011 - 03:08 AM

:p jojojo difiero amigo, pues en esta situación ambas consultas hacen lo mismo, descartan las claves no coincidentes y por tanto nunca aparecen nulos del lado derecho o izquierdo


Con la sintaxis utilizada, sí que dan el mismo resultado, pero el JOIN tiene una sintaxis flexible y rica que permite mostrar como nulos las claves no coincidentes a derecha o izquierda (como bien dice Delphius).

Ejemplo :

LEFT OUTER JOIN TablaB
ON TablaA.Campo1 = TablaB.Campo1

Saludos.
  • 0

#15 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1092 posts
  • LocationMurcia, España

Posted 09 September 2011 - 04:55 AM

Ya veo que esta resuelto el tema, pero creo que se cerro "en falso".

Nosotros hasta hoy siempre usamos "left join", nos ha valido siempre y conocemos su comportamiento muy bien, pero en FireBird 2.5 la cosa ha cambiado bastante al respecto (para mejor), en nuestro caso hemos editado todas las consultas para adecuarlas a las mejoras del optimizador, os cuento:

Voy a usar otro ejemplo para que todos vean lo que digo: Facturas unidas a clientes, donde cada factura SIEMPRE tiene un cliente (no es un dato opcional que puede ser null).

En estos casos, si usamos cualquiera de las dos formas que propones, lo mas importante es poner primero la tabla de facturas si vamos a filtrar por la fecha de factura, o poner primero la de clientes si vamos a filtrar por un dato del cliente. Esto hace, de siempre, que una consulta que tarda 10 segundos "mal hecha" pasase a 0.1 segundos arreglada.

Os pongo el ejemplo de bien y mal hecho:

select f.* from factura f
join cliente c on c.cliente=f.cliente
where c.poblacion='MURCIA'

Esta SQL esta mal, sera increiblemente lenta, porque filtramos por algo que no esta en la tabla principal, y el plan sera recorrerse TODOS los clientes aunque tengamos un indice por poblacion. La SQL correcta (antes de la V2.5) seria asi:

select f.* from cliente c
left join factura f c on c.cliente=f.cliente
where c.poblacion='MURCIA'

Obtenemos la misma lista, pero en tiempos radicalmente distintos. La pega es que te toca analizar los filtros para intercambiar las dos tablas... un lio tremendo.

Ahora, con la V2.5, esta optimizacion es automatica (y es mucha la diferencia) siempre que usemos INNER JOIN, que es el tipo de join que da por supuesto que una factura siempre tiene un cliente:

select * from factura f
INNER JOIN cliente c on c.cliente=f.cliente
where c.poblacion='MURCIA'

Esta forma de SQL funcionara a maxima velocidad tanto si filtramos por un campo de factura como por uno de cliente! El optimizador se dara cuenta de que hay un indice de poblacion en el cliente, filtrara los clientes de esa poblacion, y usara esa lista de clientes para localizar sus facturas. En el plan no vereis la temida palabra "NATURAL".

OJO porque si teneis una SQL con varios JOIN, y solo 1 o 2 son INNER, estos deben ir los primeros para que se les aplique la optimizacion: Si por ejemplo unja factura puede o no tener asociado un pedido previo, serái asi:

select * from factura f
INNER JOIN cliente c on c.cliente=f.cliente
LEFT JOIN pedido p on f.pedido=p.pedido
where c.poblacion='MURCIA'

En versiones pre 2.5 esto no mejora en nada el rendimiento, solo en la 2.5
  • 0

#16 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 09 September 2011 - 07:24 AM


:p jojojo difiero amigo, pues en esta situación ambas consultas hacen lo mismo, descartan las claves no coincidentes y por tanto nunca aparecen nulos del lado derecho o izquierdo


Con la sintaxis utilizada, sí que dan el mismo resultado, pero el JOIN tiene una sintaxis flexible y rica que permite mostrar como nulos las claves no coincidentes a derecha o izquierda (como bien dice Delphius).

Ejplo :
[pre]LEFT OUTER JOIN TablaB
ON TablaA.Campo1 = TablaB.Campo1
[/pre]

Saludos.



Coincido amigo marc. Los estándares actuales de ansi sql definen la manera en que deben ser usados los joins. Solo que como le decia a look, sus consultas son excactamente lo mismo para el servidor de base de datos.

Ahora bien, sobre el uso de left, rigth, inner o full join, dependerá del resultado que se desea obtener.

Saludox  :)  (h)
  • 0

#17 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 09 September 2011 - 07:27 AM

Ya veo que esta resuelto el tema, pero creo que se cerro "en falso".

Nosotros hasta hoy siempre usamos "left join", nos ha valido siempre y conocemos su comportamiento muy bien, pero en FireBird 2.5 la cosa ha cambiado bastante al respecto (para mejor), en nuestro caso hemos editado todas las consultas para adecuarlas a las mejoras del optimizador, os cuento:


Me ha gustado la explicación que has dado, sería grandioso que mostrarás los planes de ejecución que genera Firebird con cada consulta. Y poder ver las estadísticas de costos en tiempo y memoria. Algo como la imagen que he incluido de Sql Server.
  • 0

#18 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 09 September 2011 - 07:52 AM

He querido agregar dos planes de ejecución más de otra base de datos para mostrar que las consultas de look para el motor de base de datos son exactamente lo mismo. Ahora en este caso son con Db2.  Como les decía, ambas maneras de realizar las consultas están claramente definidas en los estándares de ansi-sql y todos los motores de bases de datos están obligados a mantener compatibilidad con esos estándares.


Estadísticas para un join  natural definido en el estándar ansi sql 86

Imagen Enviada
db22 por poliburro, en Flickr




Estadísticas para un join compatible con el estándard ansi sql 92

Imagen Enviada
db21 por poliburro, en Flickr


Ambas consultas aparecen al fondo de la gráfica. Y  como les comentaba, las estrategias de optimización de consultas no va solo en la manera que armas tus joins. Eso dependerá siempre de cosas como la creación de indices, el tipo de arreglo de discos en que la base de datos almacena la información. Para darles un ejemplo:

Tanto en oracle como en postgres es posible colocar sus archivos de índices en arreglos raid ultra rápidos para optimizar búsquedas. Así, los archivos datos pueden  ser colocados en discos no tan veloces y se optiene un entorno potente, seguro y rápido.

Otras estrategias de otpimización incluyen el uso de tablas caché, tablas temporales de sesión, uso de vistas, etc ect. Como siempre, todo dependerá de el reusltado deseado.
  • 0

#19 mightydragon_lord

mightydragon_lord

    Advanced Member

  • Miembros
  • PipPipPip
  • 73 posts

Posted 09 September 2011 - 09:03 AM

Coincido con Delphius, es totalmente diferente, te cuento compañero Poliburro, el hecho que el plan de ejecución sea igual es por que existen indices y demás, de eso se trata el plan de ejecución, analizar la consulta y ejecutarla dependiendo de varios parámetros.
  • 0

#20 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3486 posts
  • LocationMexico City

Posted 09 September 2011 - 10:42 AM

Coincido con Delphius, es totalmente diferente, te cuento compañero Poliburro, el hecho que el plan de ejecución sea igual es por que existen indices y demás, de eso se trata el plan de ejecución, analizar la consulta y ejecutarla dependiendo de varios parámetros.


Je je... no entendí... el plan de ejecución que hace el motor de la base de datos no refleja información de eficiencia de una consulta en particular, considerando claro, diseño de las tablas e índices creados en la BD en donde se está pobrando ???

Saludox ! :)
  • 0




IP.Board spam blocked by CleanTalk.