Como seguramente ya sabes, INNER JOIN es el join que se usa por defecto en SQL y por lo tanto en Firebird. La palabra INNER es opcional, si lo deseas puedes escribir solamente JOIN y eso le indica al Firebird que deseas hacer un INNER JOIN.
Cuando dos tablas están relacionadas mediante un INNER JOIN la consulta devolverá las filas que comparten valores comunes en ambas tablas.
Sin embargo, no todos los INNER JOIN que escribas tendrán la misma performance. Algunos serán más efectivos que otros. La mejor manera que tienes de averiguar cuan efectiva es tu consulta es usando un programa manejador gráfico, tal como el EMS SQL Manager. En este caso si haces click sobre la pestaña «Performance Analysis» podrás ver gráficamente la eficiencia de tu consulta.
Captura 1. Si haces clic sobre la imagen la verás más grande
Veamos un ejemplo:
Tenemos la tabla SUCURSALES con los siguientes datos:
Captura 2. Si haces clic sobre la imagen la verás más grande
y tenemos la tabla BANCOS con los siguientes datos:
Captura 3. Si haces clic sobre la imagen la verás más grande
Como ves, todos los Bancos registrados hasta ahora (16 Bancos en total) pertenecen a la Sucursal número 0, es decir a Asunción. Ahora escribimos una consulta para que nos muestre los nombres de las sucursales y los datos de los Bancos. La tabla SUCURSALES tiene un índice según la columna SUC_CODIGO y la tabla BANCOS tiene un índice según las columnas BAN_CODSUC y BAN_IDENTI.
SELECT B.BAN_CODSUC, S.SUC_NOMBRE AS BAN_NOMSUC, B.BAN_IDENTI, B.BAN_NOMBRE FROM BANCOS B JOIN SUCURSALES S ON B.BAN_CODSUC = S.SUC_CODIGO
y luego, haciendo click sobre «Performance Analysis» averiguamos que tan eficiente es nuestra consulta y esto es lo que obtenemos:
Captura 4. Si haces clic sobre la imagen la verás más grande
Evidentemente una performance muy mala. El SELECT está correcto, el JOIN se realizó correctamente, sin embargo la performance obtenida es pésima. ¿Por qué? porque en la tabla de BANCOS no se está usando un índice y la tabla de SUCURSALES fue recorrida una vez por cada fila de la tabla de BANCOS. Eso es pésimo.
Podemos mejorar esa consulta escribiendo:
SELECT B.BAN_CODSUC, S.SUC_NOMBRE AS BAN_NOMSUC, B.BAN_IDENTI, B.BAN_NOMBRE FROM BANCOS B JOIN SUCURSALES S ON B.BAN_CODSUC = S.SUC_CODIGO WHERE B.BAN_CODSUC >= 0
o sea, se agregó una cláusula WHERE obligándole así al Firebird a usar un índice en la tabla de BANCOS. La nueva performance será ahora:
Captura 5. Si haces clic sobre la imagen la verás más grande
Ya está mejor, ahora las dos tablas están usando índices. Sin embargo ¿por qué la tabla de SUCURSALES fue recorrida 16 veces siendo que solamente tenemos 4 sucursales y de esas solamente 1 sucursal está siendo utilizada?
Podemos mejorar esa consulta escribiendo:
SELECT B.BAN_CODSUC, S.SUC_NOMBRE AS BAN_NOMSUC, B.BAN_IDENTI, B.BAN_NOMBRE FROM BANCOS B JOIN SUCURSALES S ON B.BAN_CODSUC = S.SUC_CODIGO WHERE B.BAN_CODSUC >= 0 AND B.BAN_IDENTI > 0
Ahora, este es el gráfico de la performance que obtenemos:
Captura 6. Si haces clic sobre la imagen la verás más grande
Sin dudas que está mejor, ambas tablas están usando índices y la tabla de SUCURSALES solamente fue recorrida 4 veces, o sea 1 vez por cada fila de esa tabla. ¿Pero por qué fue recorrida 4 veces siendo que en la tabla de BANCOS solamente la sucursal con el código 0 es utilizada?
Esta consulta puede ser optimizada para que solamente una fila de la tabla de SUCURSALES sea visitada. ¿Cómo lo harías?
Finalmente, si solamente te interesa la sucursal número 0 lo que puedes escribir es:
SELECT B.BAN_CODSUC, S.SUC_NOMBRE AS BAN_NOMSUC, B.BAN_IDENTI, B.BAN_NOMBRE FROM BANCOS B JOIN SUCURSALES S ON B.BAN_CODSUC = S.SUC_CODIGO WHERE B.BAN_CODSUC >= 0 AND B.BAN_IDENTI > 0 AND S.SUC_CODIGO = 0
y la performance que obtendrás en ese caso será:
Captura 7. Si haces clic sobre la imagen la verás más grande
Y este es, finalmente, el mejor resultado posible. Lo importante que debes notar aquí es que con la cláusula WHERE se le obligó al Firebird a utilizar índices y que a medida que más columnas se le fueron agregando a la cláusula WHERE más se fue mejorando la performance obtenida.
Las tablas utilizadas en este ejemplo tenían pocas filas, en tablas que tienen miles o millones de filas la ganancia de tiempo puede ser impresionante. Siempre que escribas una consulta o una vista debes verificarla con la pestaña «Performance Analysis» para asegurarte que está optimizada. Y si no lo está, debes optimizarla.
Artículos relacionados:
El índice del blog Firebird21
El foro del blog Firebird21
El índice del blog Firebird21 | Firebird SQL
Jun 17, 2013 @ 04:39:58
jtraslavi
Sep 06, 2014 @ 02:33:30
Hola un saludo, más que un comentario es una duda, cuando hablas de la optimización el numero 16, 4 etc que se muestra se refiere a la cantidad de veces que se leyó la totalidad de la tabla ?, o quizá la cantidad de registros leídos ?, o quizá la cantidad de veces que se accesó la tabla durante la consulta sin importar cuantos registros se utilizaron? , la duda es exactamente como se deben interpretar esos valores ? … por ejemplo tengo una tabla de 23500 registros y en el Performance analysis me sale 47000 … debo interpretar que la tabla completa fue leída 2 veces ? … Que diferencia tendría si aparece 47000 en cilindro azul o 47000 en cilindro rojo, sería lo mismo para el rendimiento o que diferencia aparte del uso de índice habría…? Saludos y gracias por tus excelentes aportes.
wrov
Sep 06, 2014 @ 04:19:42
Esos números indican la cantidad de veces que se leyeron las filas. Si tu tabla tiene 23.500 filas y el Performance Analysis te muestra 47.000 eso te indicará que muy probablemente la tabla completa se leyó 2 veces (también podría ser que no se leyó la tabla completa sino algunas de sus filas varias veces y por una gran casualidad esa cantidad fue de 47.000)
Un 47.000 en azul te indica que se leyeron 47.000 filas usando un índice. Un 47.000 en rojo te indica que se leyeron 47.000 filas sin usar un índice.
¿Hay diferencia en velocidad? Sí, si no se usa un índice la velocidad es mayor porque si se usa un índice primero hay que leer su valor y luego se accede a la fila, ese primer paso se evita si no se usa un índice.
Hay ocasiones en que es mejor no usar un índice, por ejemplo cuando no te importa el orden en el cual se muestran las filas.
Un índice se usa para mostrar las filas ordenadas o para filtrar las filas que serán mostradas. Si la cantidad de filas que te muestra el Performance Analysis es la misma usando un índice o no usándolo, deberías comprobar si realmente necesitas un índice ya que es muy probable que no lo necesites.
Por supuesto que si la cantidad de filas es significativamente menor cuando usas un índice entonces sí deberías usarlo.
Saludos.
Walter.
Arturo Zamudio
Oct 23, 2014 @ 00:13:06
Una pregunta, en el sql manager lite for interbase hago el sig select
SELECT a.matricula,a.nombre||’*’||a.apaterno,b.seccion,b.grupo
FROM alumnos a
join
datos_ciclo b
on a.matricula=b.MATRICULA
where b.CICLO LIKE ‘2014%’ AND
b.STATUS=’ACTIVO’ AND
B.SECCION=’PRIMARIA’
y me da los resultados que requiero, pero ahora quiero saber como le mando el select por medio del vfp
itenté con el siguiente y no me da los resultados
SQLEXEC(FIRECONEX,’SELECT a.matricula,a.nombre||’*’||a.apaterno,b.seccion,b.grupo FROM alumnos a join datos_ciclo b on a.matricula=b.MATRICULA where b.CICLO LIKE «2014%» AND b.STATUS=»ACTIVO» AND B.SECCION=»PRIMARIA»‘)
gracias
Arturo Zamudio
Oct 23, 2014 @ 00:19:19
ya encontre mi error, le faltaba el signo ? despues de la condicion que requeria
wrov
Oct 23, 2014 @ 00:27:57
Bueno, primero, te aconsejo que a tus SELECTs los ordenes mejor para que sea más fácil leerlos y comprenderlos, o sea escribirlos así:
Donde, como puedes notar, es más legible todo.
Segundo, en lugar de escribir dentro del SELECT tu consulta es preferible que uses una variable para ella, algo como:
Es más fácil de leer, más entendible, y más rápido se detectan los errores.
Pero volviendo a tu problema es que has usado comillas dentro del SELECT y eso el VFP lo permite pero el Firebird no. En el Firebird solamente están permitidos los apóstrofos. En Firebird escribir B.SECCION = «PRIMARIA» es un error, porque las comillas no pueden ser utilizadas allí.
Así que la solución es rodear al argumento con comillas e internamente usar apóstrofos, algo como:
Fíjate en el uso de la comillas y de los apóstrofos.
Saludos.
Walter.
Arturo Zamudio
Oct 23, 2014 @ 00:52:54
mil gracias, cada dia aprendo mas.
omar
Jun 12, 2015 @ 15:04:07
contiene muy buena información
cipce22
Ago 27, 2015 @ 20:27:07
Al crear los indices y utilizandolos con el where, se mejora un poco el tiempo, casi todas las lecturas son indexadas pero hay un inconveniente, al hacer esto se aumentan las lecturas en 20%, a qué se debe?
todos tus aportes me han ayudado a aprender cada dia
wrov
Ago 27, 2015 @ 23:34:12
Si usas un índice, el Firebird primero debe buscar su clave en una «página de índices» y luego recupera los datos que te interesan de una «página de datos». Si no usas un índice, solamente se lee la «página de datos».
Los índices son muy útiles cuando no se recorrerá toda la tabla o cuando se desea ver las filas ordenadas. En los demás casos suele ser mejor no usarlos.
Si deseas filtrar (cláusula WHERE), enlazar (cláusula JOIN), agrupar (cláusula GROUP BY) u ordenar (cláusula ORDER BY) entonces al usar índices se consigue obtener los resultados más rápido aunque a veces la cantidad de extracciones (fectch) es mayor si se los usa.
Saludos.
Walter.
mikitest69iki
Nov 16, 2015 @ 13:50:09
He visto un abuso masivo de la palabra inglesa «perfomance». El idioma español es muy rico, y es mucho mas bonito decir:
Sin embargo, no todos los INNER JOIN que escribas tendrán el mismo rendimiento.
wrov
Nov 16, 2015 @ 15:16:27
Es cuestión de opinión, y quizás también del país o región donde vivas.
Saludos.
Walter.
gare
Jun 28, 2018 @ 11:58:33
estoy realizando una consulta mediante un inner join pero me manda un error de termino de tiempo al ejecutar la consulta, supongo que es por la cantidad de información que estoy manipulando, alguien me podría explicar como poder optimizar el tiempo de ejecución o cuales con los parámetros correctos que puedo emplear en el my.ini, ya que el total de registros que intento unir son de mas de 7 millones.
wrov
Jun 28, 2018 @ 13:42:45
¿Qué es el MY.INI?