Consejos prácticos para escribir mejores consultas SQL

9 trucos para mejorar el rendimiento de las consultas SQL

Consejos prácticos para escribir mejores consultas SQL

El rendimiento general de cualquier aplicación rica en datos depende en gran medida del tiempo de ejecución de una operación de base de datos. Todos los días se escriben muchas consultas SQL en línea. Todas las consultas que se parecen no tienen un rendimiento similar. El ajuste fino de una consulta puede cambiar drásticamente el rendimiento de su aplicación. Por lo tanto, escriba cada línea de una consulta con cuidado.


En este artículo, enumeraré algunas técnicas cotidianas que mejorarán el rendimiento de tus consultas SQL.


1. SELECCIONAR campos en lugar de usar SELECT *

SELECT* (leído como select all) se utiliza a menudo para consultar todos los datos de una tabla. Aunque este método funciona bien para tablas pequeñas, sobrecarga innecesariamente los recursos de la base de datos cuando se lanza una consulta sobre una tabla con muchos campos y filas.


El mejor enfoque en este caso es definir los campos en la declaración SELECT para indicar a la base de datos que consulte sólo los datos necesarios para cumplir los objetivos finales.

Vamos a entenderlo mejor con la ayuda de un ejemplo. Esta es una forma ineficiente, ya que esta consulta obtendrá todos los datos almacenados en la Users tabla independientemente de sus necesidades:

SELECT* FROM Users;

Esta es la forma más eficiente de realizar consultas, ya que sólo extrae la información necesaria y evita que su base de datos se cargue:

SELECT LastName, Address, Contact FROM Users;


2. Cree índices correctamente

El ajuste del rendimiento en SQL se puede hacer indexando correctamente, lo que se traduce en un acceso más rápido a la base de datos en momentos críticos. Esta es un área en la que la mayoría de los novatos en bases de datos se quedan cortos. Intentan indexar todo o nada, y ninguno de estos enfoques funciona a su favor.


Esto se debe a que cuando no se hace ningún tipo de indexación, las consultas se ejecutan lentamente y suponen una carga innecesaria para la base de datos. Por otro lado, si indexa todo, sus activadores de inserción no funcionarán como se espera, haciendo que su base de datos sea ineficiente.

La clave aquí es encontrar el equilibrio adecuado.


3. Utilice las tablas temporales con prudencia

Aunque las tablas temporales son estupendas, aumentan exponencialmente la complejidad de una consulta. Se recomienda encarecidamente evitar el uso de tablas temporales si su código puede escribirse de forma sencilla.


Sin embargo, si necesitas lidiar con un procedimiento almacenado que no puede ser manejado con una sola consulta, usar tablas temporales como intermediarias puede ser una decisión más inteligente.


4. Evite el uso de COUNT ()

Una de las formas más comunes en que los desarrolladores comprueban si un determinado registro existe es utilizando COUNT() en lugar de EXISTS(). COUNT() es ineficiente porque escanea toda la tabla y cuenta todas las consultas que satisfacen su condición. En cambio, EXISTS() es más eficiente porque sale del bucle en cuanto detecta el resultado deseado. Esto contribuye a un mejor rendimiento y a un código más ordenado.


5. Evite el uso de caracteres comodín al comienzo del patrón LIKE

Para afinar sus consultas SQL, debe evitar el uso del patrón LIKE de la siguiente manera:

SELECT* FROM Customers WHERE address LIKE ‘%bar%’;

En este caso, la base de datos no podrá utilizar un índice adecuado si existe a causa del % comodín. El sistema comienza realizando un escaneo completo de la tabla, y esto afecta a su velocidad. Por lo tanto, la mejor manera de escribir esta consulta es:

SELECT* FROM Customers WHERE address LIKE ‘bar%’;


6. Evite el uso de SELECT DISTINCT

Aunque puede eliminar fácilmente los duplicados de una consulta utilizando SELECT DISTINCT, esta función consume una gran cantidad de potencia de procesamiento. Además, esta consulta funciona agrupando todos los campos de la consulta para presentar resultados distintos. Esto, a su vez, hace que sea muy imprecisa.


La mejor manera de evitar los registros duplicados en la consulta es añadir más campos. De este modo, no será necesario agrupar y los registros obtenidos serán precisos.


Por ejemplo, esta es una forma ineficiente de hacerlo:

SELECT DISTINCT FirstName, LastName, State FROM Users;

Y esta es la forma eficiente de hacerlo

SELECT FirstName, LastName, Contact, Address, State, Zip FROM Users;


7. Cree uniones con INNER JOIN (no WHERE)

Algunos desarrolladores de SQL prefieren hacer las uniones con cláusulas WHERE. Por ejemplo:

SELECT Customers.CustomerID, Customers.Name, Sales.LastSaleDate FROM Customers, Sales WHERE Customers.CustomerID = Sales.CustomerID;

Este tipo de combinación crea una combinación cartesiana, también llamada producto cartesiano o CROSS JOIN.


En una combinación cartesiana, se crean todas las combinaciones posibles de las variables. En este ejemplo, si tuviéramos 1.000 clientes con 1.000 ventas totales, la consulta generaría primero 1 millón de resultados y luego filtraría por los 1.000 registros donde CustomerID se unió correctamente. Esto es un uso ineficiente de los recursos de la base de datos, ya que ésta ha hecho 100 veces más trabajo del necesario.


Las uniones cartesianas son especialmente problemáticas en las bases de datos a gran escala porque una unión cartesiana de dos tablas grandes podría generar miles de millones o trillones de resultados.


Para evitar crear una unión cartesiana, utilice INNER JOIN en su lugar:

SELECT Customers.CustomerID, Customers.Name, Sales.LastSaleDate FROM Customers INNER JOIN Sales ON Customers.CustomerID = Sales.CustomerID;

La base de datos sólo generaría los 1.000 registros deseados cuando CustomerID sea igual.


Algunos sistemas DBMS pueden reconocer las uniones WHERE y ejecutarlas automáticamente como en su lugar INNER JOINS. En esos sistemas DBMS, no habrá diferencia en el rendimiento entre una combinación WHERE y un INNER JOIN. Sin embargo, todos los sistemas SGBD reconocen el INNER JOIN.

Su DBA le aconsejará cuál es el mejor en su entorno.

8. Utilice WHERE en lugar de HAVING para definir los filtros

El objetivo de una consulta eficiente es extraer sólo los registros necesarios de la base de datos. Según el orden de operaciones de SQL, las sentencias HAVING se calculan después de las sentencias WHERE. Si la intención es filtrar una consulta basada en condiciones, una sentencia WHERE es más eficiente.


Por ejemplo, supongamos que se han realizado 200 ventas en el año 2021 y queremos consultar el número de ventas por cliente en 2021:

SELECT Customers.CustomerID, Customers.Name, Count(Sales.SalesID)
FROM Customers
INNER JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.CustomerID, Customers.Name
HAVING Sales.LastSaleDate BETWEEN #1/1/2021# AND #12/31/2021#;

Esta consulta extraería 1.000 registros de ventas de la tabla Sales, filtraría los 200 registros generados en el año 2021 y, finalmente, contaría los registros en el conjunto de datos.


En comparación, las cláusulas WHERE limitan el número de registros extraídos:

SELECT Customers.CustomerID, Customers.Name, Count(Sales.SalesID) FROM Customers INNER JOIN Sales ON Customers.CustomerID = Sales.CustomerID WHERE Sales.LastSaleDate BETWEEN #1/1/2021# AND #12/31/2021# GROUP BY Customers.CustomerID, Customers.Name;

Esta consulta extraería los 200 registros para el año 2021 y luego los publicaría en el conjunto de datos. HAVING ha eliminado el primer paso de la cláusula.


HAVING sólo debe utilizarse cuando se filtre en un campo agregado. En la consulta anterior, también podríamos filtrar los clientes con más de cinco ventas utilizando una sentencia HAVING:

SELECT Customers.CustomerID, Customers.Name, Count(Sales.SalesID) FROM Customers INNER JOIN Sales ON Customers.CustomerID = Sales.CustomerID WHERE Sales.LastSaleDate BETWEEN #1/1/2021# AND #12/31/2021# GROUP BY Customers.CustomerID, Customers.Name HAVING Count(Sales.SalesID) > 5;


9. Ejecute las operaciones masivas durante las horas de menor actividad.

Para reducir el impacto de sus consultas analíticas en la base de datos de producción, hable con un DBA para programar la consulta para que se ejecute durante las horas de menor actividad. La consulta debe ejecutarse cuando los usuarios concurrentes estén en su número más bajo, que suele ser a mitad de la noche (de 3 a 5 de la mañana).


Cuanto más criterios tenga la consulta, más probable será que se ejecute por la noche:

  • Selección de tablas grandes (> 1 millón de registros).
  • Uniones cartesianas o CROSS JOINS
  • Sentencias de bucle
  • Sentencias SELECT DISTINCT
  • Subconsultas anidadas
  • Búsquedas con comodines en campos de texto largos o notas
  • Consultas multi-esquema

Conclusión


El ajuste del rendimiento de las consultas SQL es muy importante para mantener su base de datos en buen estado, pero no es fácil. El rendimiento de las consultas SQL depende de una serie de factores, como el diseño de la base de datos y el tipo de datos. Las aplicaciones grandes y complejas suelen crear requisitos complejos. Eso lleva a escribir consultas SQL complejas. Estas sencillas prácticas pueden marcar una gran diferencia en los tiempos de respuesta de su base de datos.


Gracias por leer mi artículo. Espero que le haya resultado útil.