Compartir por


Problemas de rendimiento de T-SQL

Se aplica a: SQL Server Azure SQL Database Azure SQL Managed Instance

Al analizar el código T-SQL en el proyecto de base de datos, una o varias advertencias podrían clasificarse como problemas de rendimiento. Debe solucionar los problemas de rendimiento para evitar la situación siguiente:

  • Un recorrido de tabla se produce cuando se ejecuta el código.

En general, puede suprimir un problema de rendimiento si la tabla contiene tan pocos datos que un examen no hará que el rendimiento baje significativamente.

Las reglas proporcionadas identifican los siguientes problemas de rendimiento:

SR0004: Evite usar columnas que no tengan índices como expresiones de prueba en predicados IN

Se produce un recorrido de tabla si se usa una cláusula WHERE que hace referencia a una o varias columnas sin índices como parte de un predicado IN. El recorrido de tabla reduce el rendimiento.

Cómo corregir infracciones

Para corregir este problema, debe realizar uno de los cambios siguientes:

  • Cambie el predicado IN para hacer referencia solo a las columnas que tienen un índice.
  • Agregue un índice a cualquier columna a la que hace referencia el predicado IN y que aún no tiene un índice.

Ejemplo

En este ejemplo, una instrucción SELECT simple hace referencia a una columna, [c1], que no tenía índice. La segunda instrucción define un índice que puede agregar para resolver esta advertencia.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
AS
SELECT [Comment]
FROM [dbo].[Table2]
WHERE [c1] IN (1, 2, 3)

CREATE INDEX [IX_Table2_C1]
ON [dbo].[Table2] (c1);

SR0005: Evite usar patrones que empiecen por "%" en predicados LIKE

Podría provocar un recorrido de tabla si usa una cláusula WHERE que contiene un predicado LIKE, como "%cadena de patrón" para buscar texto que pueda producirse en cualquier parte de una columna.

Cómo corregir infracciones

Para resolver este problema, debe cambiar la cadena de búsqueda para que comience con un carácter que no sea un carácter comodín (%) o debe crear un índice de texto completo.

Ejemplo

En el primer ejemplo, la instrucción SELECT provoca un recorrido de tabla porque la cadena de búsqueda comienza con un carácter comodín. En el segundo ejemplo, la instrucción provoca una búsqueda de índice porque la cadena de búsqueda no comienza con un carácter comodín. Una búsqueda de índice recupera solo las filas que coinciden con la cláusula WHERE.

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE '%pples'

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE 'A%'

SR0006: Mueva una referencia de columna a un lado de un operador de comparación para usar un índice de columna

El código podría provocar un recorrido de tabla si compara una expresión que contiene una referencia de columna.

Cómo corregir infracciones

Para resolver este problema, debe volver a realizar la comparación para que la referencia de columna aparezca sola en un lado del operador de comparación, en lugar de dentro de una expresión. Al ejecutar el código que tiene solo la referencia de columna en un lado del operador de comparación, SQL Server puede usar el índice de columna y no se realiza ningún recorrido de tabla.

Ejemplo

En el primer procedimiento, una cláusula WHERE incluye la columna [c1] en una expresión como parte de una comparación. En el segundo procedimiento, los resultados de la comparación son idénticos, pero nunca requieren un recorrido de tabla.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] + 5 > @param1)

CREATE PROCEDURE [dbo].[Procedure3Fixed]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] > (@param1 - 5))

SR0007: Use ISNULL(column, default_value) en columnas que aceptan valores NULL en expresiones

Si el código compara dos valores NULL o un valor NULL con cualquier otro valor, el código devuelve un resultado desconocido.

Cómo corregir infracciones

Debe indicar explícitamente cómo controlar los valores NULL en expresiones de comparación ajustando cada columna que puede contener un valor NULL en una función ISNULL.

Ejemplo

En este ejemplo se muestra una definición de tabla simple y dos procedimientos almacenados. La tabla contiene una columna, c2, que puede contener un valor NULL. El primer procedimiento, ProcedureWithWarning, compara c2 con un valor constante. El segundo procedimiento corrige el problema encapsulando c2 con una llamada a la función ISNULL.

CREATE TABLE [dbo].[Table1]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL PRIMARY KEY,
[c2] INT
)
ON [PRIMARY]

CREATE PROCEDURE [dbo].[ProcedureWithWarning]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
 WHERE [c2] > 2;
END

CREATE PROCEDURE [dbo].[ProcedureFixed]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
WHERE ISNULL([c2],0) > 2;
END

SR0015: Extraiga llamadas de función deterministas de predicados WHERE

En un predicado WHERE, una llamada de función es determinista si su valor no depende de los datos seleccionados. Estas llamadas podrían provocar recorridos de tabla innecesarios, lo que reduce el rendimiento de la base de datos.

Cómo corregir infracciones

Para resolver este problema, puede asignar el resultado de la llamada a una variable que use en el predicado WHERE.

Ejemplo

En el primer ejemplo, el procedimiento almacenado incluye una llamada de función determinista, ABS(@param1), en el predicado WHERE. En el segundo ejemplo, una variable temporal contiene el resultado de la llamada.

CREATE PROCEDURE [dbo].[Procedure2WithWarning]
@param1 INT = 0,
AS
BEGIN
SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > ABS(@param1)
END

CREATE PROCEDURE [dbo].[Procedure2Fixed]
@param1 INT = 0,
AS
BEGIN
DECLARE @AbsOfParam1 INT
SET @AbsOfParam1 = ABS(@param1)

SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > @AbsOfParam1
END