Visitas: 15  
Tiempo total: 0 días con 8:22:3 hrs  

La función de RIGHT JOIN es devolver todos los registros de la tabla a la derecha, si existe alguna coincidencia devolverá los valores de la tabla a la izquierda, caso contrario devolverá NULL en vez de dichos valores.

Right join

Optimizando una atrocidad

Dada la siguiente consulta SQL, considere el problema: la consulta tarda tiempo infinito en ejecutarse.

SELECT 
c.tipo, 
SUM(cp.cantidad) as cantidad, 
SUM(IF(DATE(p.fecha) = '2019-03-20', cp.cantidad, 0)) as cantidad_hoy
FROM 
contrato_pagado cp
RIGHT JOIN contrato_no_pagado cnp ON cp.contrato_no_pagado= cnp.id
RIGHT JOIN contrato c ON cnp.contrato = c.id
RIGHT JOIN pago p ON cp.pago = p.id
WHERE 
AND DATE(p.fecha) >= '2019-03-18'
AND DATE(p.fecha) <= '2019-03-24'
GROUP BY c.tipo

En una tabla de unos cuantos registros, dicha consulta se ejecutará sin problemas, pero que sucede cuando existen muchos registros? Tienes idea de porque el programador utilizo RIGHT JOIN en la consulta? No sabes si el RIGHT JOIN está para lograr hacer algún calculo? En general, de qué manera puedo optimizar una consulta?

Simplificación de consulta

El primer paso para optimizar una consulta es simplificándola, nos quedará así:

  1. cp
  2. cnp RIGHT JOIN cp.cnp = cnp.id
  3. c RIGHT JOIN cnp.c = c.id
  4. p RIGHT JOIN cp.p = p.id

WHERE 2019-03-18 < p.f < 2019-03-24

Aquí observamos cómo están relacionadas las tablas. Con esto, podemos armar un gráfico simple para aclarar más lo que el programador estaba haciendo:

Con el gráfico anterior, tenemos que preguntarnos: que campos se muestran en el SELECT?

La consulta gira en torno a la sumatoria de los valores CP, así que es innecesario obtener registros de CNP o de P en donde los valores de CP sean NULL. En base a esto, hagamos el gráfico real de los datos que nos interesan:

Las condicionales en WHERE limitan los registros seleccionados.

Observamos que no es necesario utilizar los RIGHT JOIN: los datos a la derecha no nos interesan en ningún caso. El SQL optimizado debería de ser:

SELECT 
c.tipo, 
SUM(cp.cantidad) as cantidad, 
SUM(IF(DATE(p.fecha) = '2019-03-20', cp.cantidad, 0)) as cantidad_hoy
FROM 
contrato_pagado cp
JOIN contrato_no_pagado cnp ON cp.contrato_no_pagado= cnp.id
JOIN contrato c ON cnp.contrato = c.id
JOIN pago p ON cp.pago = p.id
WHERE 
AND DATE(p.fecha) >= '2019-03-18'
AND DATE(p.fecha) <= '2019-03-24'
GROUP BY c.tipo

Con solo eliminar los RIGH JOIN por un simple JOIN, pasamos de un tiempo infinito a milésimas de segundo.

0