SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Siempre que uno se dispone a programar un SQL Query, trata de hacerlo lo más sencillo que se pueda. Claro, esto nos enseñan en la universidad, pero una cosa es la teoría y otra es, la realidad. Esto desde un punto de vista algo ligero puede parecer ideal. Sin embargo, muchas veces nos olvidamos de tomar encuentra una variable muy pero muy importante como lo es el rendimiento. La idea no es programar una consulta con tal que nos devuelva el resultado deseado asi de simple, sino que, por encima de vuestros facilitismos académicos debe predominar la calidad y rendimiento de un SQL Query .

Es así que, mediante este post se pretende demostrar que lo "fácil" tiene un costo de rendimiento, y aveces esto suele ser muy elevado. Digo esto porque mucho se escucha decir que un SQL Self-Join  se usa para simplificar un SQL Nested-Join, y que bla.. bla... bla.. y que en muchos sitios se recomienda, pero como ya dije y vuelvo a decir (las veces que sean necesarias), todo esto tiene un costo de rendimiento que se incrementa de acuerdo al tipo de data y la cantidad de la misma que se consulte.

En esta demostración he tomado por conveniente confrontar los resultados de dos tipos de consultas muy conocidas, y antes comentada, como son los SQL Self-Join y SQL Nested-Join. Como sabéis, un self-join es un SQL Join que une una tabla con ella misma.  Esto es posible gracias al uso de alias para cada tabla consiguiendo de esta manera una instancia de cada tabla por separado para poder trabajar sobre ellas. Esto es de gran ayuda pero no te olvides del rendimiento. A continuación unos ejemplos de este tipo de query :

SQL Self-Join 01

SELECT E1.EMPLOYEENAME AS EMPLOYEE,
       E2.EMPLOYEENAME AS MANAGER
FROM   EMPLOYEES AS E1
       INNER JOIN EMPLOYEES AS E2
         ON E1.MANAGERID = E2.EMPLOYEEID

SQL Self-Join 02

USE ADVENTUREWORKS

GO

SELECT   DISTINCT PV1.PRODUCTID,
                  PV1.VENDORID
FROM     PURCHASING.PRODUCTVENDOR PV1
         INNER JOIN PURCHASING.PRODUCTVENDOR PV2
           ON PV1.PRODUCTID = PV2.PRODUCTID
              AND PV1.VENDORID <> PV2.VENDORID
ORDER BY PV1.PRODUCTID

Por otra parte, debe quedar claro que un SQL Nested-Join es un tipo de consulta anidada como por ejemplo:

SELECT *
FROM   PERSON.CONTACT C1
WHERE  C1.FIRSTNAME IN (SELECT FIRSTNAME
                        FROM   PERSON.CONTACT
                        WHERE  MIDDLENAME = 'D'
                               AND LASTNAME = 'Cox')

Ahora que ya se sabe que es un Self-Join y un Nested-Join, pasaremos a realizar la demostración usando la tabla Persona.Contact( de la base de datos AdventureWorks) que contiene 19972 registros. Para esto se usará el Nested Query anterior y el siguiente SQL Self-Join Query:

SELECT *
FROM   PERSON.CONTACT C1,
       PERSON.CONTACT C2
WHERE  C1.FIRSTNAME = C2.FIRSTNAME
       AND C2.MIDDLENAME = 'D'
       AND C2.LASTNAME = 'Cox'

Estas dos consultas devuelven el mismo resultado. Claro y desde luego que un Self-Join simplifica mucho el trabajo pero veremos que esto no es conveniente en muchos casos, como tampoco lo es para esta vez. La demostración toma como variables de medida a los planes de ejecución de cada tipo de consulta, donde la consulta:

SELECT *
FROM   PERSON.CONTACT C1
WHERE  C1.FIRSTNAME IN (SELECT FIRSTNAME
                        FROM   PERSON.CONTACT
                        WHERE  MIDDLENAME = 'D'
                               AND LASTNAME = 'Cox')

...tiene como plan de ejecución a lo siguiente:

y la para la consulta:

SELECT *
FROM   PERSON.CONTACT C1,
       PERSON.CONTACT C2
WHERE  C1.FIRSTNAME = C2.FIRSTNAME
       AND C2.MIDDLENAME = 'D'
       AND C2.LASTNAME = 'Cox'

...su plan de ejecución es esto:

Podrás verificar que trabajando con una tabla de 19972 registros (de 15 columnas),  un Nested-Join es más óptimo que un Self-Join(me baso en los planes de consulta para afirmar esto). En consecuencia, las diferencias de rendimiento para cada tipo de consulta se verán muy marcadas cuando, por ejemplo, se trabaje sobre varios millones de registros. Es así que se recomienda evaluar el rendimiento de las consultas, ya sea mediante un plan de ejecución u otra forma, para elegir el método a usar para programar sus queries.

Espero que les sea de utilidad todo esto. Todas sus sugerencias y recomendaciones dejénlo por favor como un comment.

SaludosCool

Published 3/10/2006 1:30 por Percy Reyes
Comparte este post:
http://geeks.ms/blogs/ozonicco/archive/2006/10/03/SQL-Self_2D00_Join-vs-SQL-Nested_2D00_Join-_2D002600_gt_3B00_-Facilistismo-vs.-Rendimiento_2E00_.aspx

Comentarios

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Oye percy, creo que debes revisar la explicación ;) te has liado un poco o me he liado yo:

Aquí dices que esto es nu Nested-Join:

Por otra parte, debe quedar claro que un SQL Nested-Join es un tipo de consulta anidada como por ejemplo:

SELECT *

FROM   PERSON.CONTACT C1

WHERE  C1.FIRSTNAME IN (SELECT FIRSTNAME

                       FROM   PERSON.CONTACT

                       WHERE  MIDDLENAME = 'D'

                              AND LASTNAME = 'Cox')

Y aqui que esto es un self-join:

Para esto se usará el Nested Query anterior y el siguiente SQL Self-Join Query:

SELECT *

FROM   PERSON.CONTACT C1,

      PERSON.CONTACT C2

WHERE  C1.FIRSTNAME = C2.FIRSTNAME

      AND C2.MIDDLENAME = 'D'

      AND C2.LASTNAME = 'Cox'

y en el plan de ejecucución es menos costoso el Self-Join(16%) que el Nested-join (17%):

un Nested-Join es más óptimo que un Self-Join(me baso en los planes de consulta para afirmar esto).

Puede ser???

Thursday, October 05, 2006 12:07 PM por Luis Ruiz Pavón

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Gracias amigo Luis Ruiz Pavón, :P:P

efectivamente, los gráficos se habian intercambiado, o mejor dicho yo las confundí, pero ya las ubiqué donde debían estar inicialmente...

muchas gracias por la alerta!!!

alguna sugerencia, dejénselo por favor!!!...

Saludos.

Friday, October 06, 2006 5:28 AM por Percy Reyes

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Me podrias ayudar?

ten dos tablas relacionadas por un campo id. La cosa es que en algunos casos, puede haber en la segunda tabla dos id que corresponden a la misma de la primera tabla. Querría hacer una consulta que me sacara una fila por cada coincidencia, de modo que cuando se de este caso y coincidan 3, aparezcan todas en el mismo registro

Thursday, November 29, 2007 1:31 PM por ana@ap68.es

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Segun la imagen, la diferencia es de 1% hash match, y eso es para 19972 registros de 15 columnas, no habria ese 1% en tablas menores.

Deberias de haber corrido una consulta mas dificil para que se vea la diferencia.

Thursday, December 06, 2007 8:40 PM por Javier Cabanillas Rodríguez

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Hola percy he leido la mayoría de tus blogs, me gustaría saber que es mas recomendable al hacer un query... (con respecto a utilizar inner join o no utilizarlo)

Así:

select id.medicos, nombre.medicos, telefono.medicos, calle.domicilio, no.domicilio, colonia.domicilio from medicos, domicilio where id.medicos = id.domicilio

ó:

select id.medicos, nombre.medicos, telefono.medicos, calle.domicilio, no.domicilio, colonia.domicilio from medicos inner join domicilio on id.medicos = id.domicilio

cual me conviene mas utilizar.

Thursday, February 21, 2008 8:52 PM por Lucy

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Hola, yo tambien estoy buscando formas de optimizar o al menos buscar el mejor camino para acceder a datos

El caso es que el análisis expuesto me da que pensar, ya que si, es cierto que uno tiene un 16 y otro un 17, pero tengo dos dudas

1) ¿Que pasa cuando en vez de filtros fijos, los datos deben de ser cruzados campo a campo?

2) Al hacer la prueba yo me sale exactamente lo mismo, habría que porbarlo con mas registros

Saludos

Tuesday, April 08, 2008 5:03 PM por Javierobick

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Hombre, llegué a esta página buscando una solución a mi problema y he encontrado dos. Muchas gracias por tu dedicación.

Saludos.

Wednesday, June 11, 2008 5:52 AM por Guatón Campero

# re: SQL Self-Join vs SQL Nested-Join -> Facilistismo vs. Rendimiento.

Realmente leo y releo y no entiendo la conclusión. Te basas en el redondeo que hizo el SQL server para mostrar que  HashMatch tomó 16 % y otro 17% ? Me parece poco acertada la forma de comparar. Ese indicador demuestra que porcentaje de la consulta tomó esa operación (en forma relativa al total). Quizá al evaluar el tiempo total en CPU cicles que tomó una y otra consulta te lleves una sorpresa.

SQL Server optimiza las consultas y ambas se comportan de la misma manera.

Probablemente si ejecutas las dos en simulataneo te da que el tiempo total del Batch es de 50% each.

Tuesday, August 05, 2008 9:59 PM por Martin