Anuncios en tutorial de programación PLSQL

miércoles, 18 de enero de 2023

¿Qué es mejor para el rendimiento, utilizar consultas PLSQL con subqueries o con joins?

Alguna vez me han llegado cuestiones en la que se me preguntaba qué es mejor, en términos de rendimiento de las bases de datos Oracle, si utilizar en las consultas PLSQL subqueries (subconsultas) o utilizar joins (es decir, listar todas las tablas en la clausula FROM y unirlas en el WHERE). Lo primero que hay que tener claro es que escribir una consulta PL/SQL utilizando subqueries o utilizando joins es semánticamente diferente; además, utilizar una u otra forma puede derivar en que ambas consultas devuelvan resultados diferentes y que no sean directamente intercambiables.

Subqueries vs Joins

Lo que yo recomiendo para elegir entre un tipo de consulta u otro es, en general, hacer lo siguiente:

  • Utilizar una subquery o subconsulta cuando no se necesita ninguna columna de la tabla que es referenciada en la subquery.
  • Utilizar un join en caso de necesitar alguna de las columnas.

Para intentar dejar las cosas algo más claras os dejo el siguiente ejemplo:

SELECT * 
FROM   pedidos
WHERE  tipo_pedido IN
(SELECT tipo_pedido 
FROM   tipo_pedidos);

SELECT p.* 
FROM   pedidos p, 
tipo pedidos t
WHERE  p.tipo_pedido = t.tipo_pedido;

Mi opinión es que es mejor utilizar el primer SELECT, pero única y exclusivamente por razones semánticas, ya que la primera consulta es más fácil de "leer" que la segunda. Mientras que el primer SELECT lo que nos dice es "estoy obteniendo todos los registros de la tabla pedidos tales que el campo pedidos.tipo_pedido esté en la tabla tipo_pedidos", la segunda consulta lo que nos dice es "estoy juntando la tabla pedidos con la tabla tipo_pedidos". No obstante, para el optimizador de la base de datos Oracle ambas consultas son idénticas y el rendimiento de ambas será el mismo.

Otro aspecto a recordar es que normalmente una subconsulta o subquery no puede reemplazarse por un join o viceversa, la razón es que a menudo los resultados que devolverán serán diferentes. Por ejemplo:

SQL> SELECT * 
2   FROM tipo_pedidos
3   WHERE tipo_pedido IN
4    (SELECT tipo_pedido 
5    FROM pedidos)
6   /

ID TIPO_PEDIDO
-- -----------
1 Online
2 Tienda

2 rows selected.

SQL> SELECT t.* 
2   FROM pedidos p, tipo pedidos t
3   WHERE p.tipo_pedido = t.tipo_pedido
4   /

ID TIPO_PEDIDO
-- -----------
1 Online
1 Online
..............
1 Online
2 Tienda
..............
2 Tienda

14321 rows selected.

En conclusión, el optimizador de la base de datos Oracle siempre sabrá que es lo que tiene que hacer, por lo que a la hora de construir una consulta PL/SQL y valorar si utilizar una subquery o un join, deberemos tener en cuenta que una y otra manera de construir una consulta no son, por lo general, intercambiables, y de ser posible elegir, deberemos escoger aquella que sea más sencilla de interpretar.

Artículos relacionados: El almacenamiento de subconsultas PLSQL.

3 comentarios:

bitelmaniaco dijo...

Y no sería mejor usar un EXISTS?

SELECT *
FROM pedidos p
WHERE EXISTS
(SELECT 1
FROM tipo_pedidos t
WHERE p.tipo_pedido = t.tipo_pedido
AND ROWNUM < 0);

Lo he visto más que la "clausula" IN para mejorar la optimización.

Saludos!

JLPM dijo...

Bitelmaniaco, por lo general sí pero no siempre. En este caso concreto el rendimiento será similar. Por cierto, imagino que cuando escribiste ROWNUM < 0 quisiste escribir ROWNUM < 2.

bitelmaniaco dijo...

Normalmente yo uso antes un EXISTS que un IN por temas del Explain Plan, ya que teóricamente tiene un Coste menor.

El ROWNUM lo escribí al revés, quería haber dicho ROWNUM > 0. Así en cuanto encuentre el primero, que es de lo que se trata, "sale" de esa subquery.

Por cierto, enhorabuena por el blog. Me gusta bastante!