Partager via


Problèmes de performances T-SQL

S’applique à : SQL Server Azure SQL Database Azure SQL Managed Instance Base de données SQL dans Microsoft Fabric

Lorsque vous analysez le code T-SQL de votre projet de base de données, un ou plusieurs avertissements peuvent être classés comme des problèmes de performance. Vous devez résoudre les problèmes de performance afin d'éviter la situation suivante :

  • Une analyse de table se produit lorsque le code est exécuté.

En général, vous pouvez supprimer un problème de performance si la table contient si peu de données qu'une analyse n'entraînera pas de baisse significative des performances.

Les règles fournies identifient les problèmes de performance suivants :

SR0004 : éviter d'utiliser des colonnes qui n'ont pas d'index comme expressions de test dans les prédicats IN

Vous déclenchez une analyse de table si vous utilisez une clause WHERE qui fait référence à une ou plusieurs colonnes non indexées dans le cadre d'un prédicat IN. L’analyse de table réduit les performances.

Comment corriger les violations

Pour résoudre ce problème, vous devez effectuer l'une des modifications suivantes :

  • Modifiez le prédicat IN pour qu'il ne fasse référence qu'aux colonnes qui ont un index.
  • Ajoutez un index à toute colonne à laquelle le prédicat IN fait référence et qui n'a pas encore d'index.

Exemple

Dans cet exemple, une simple instruction SELECT fait référence à une colonne, [c1], qui n'a pas d'index. La deuxième instruction définit un index que vous pouvez ajouter pour résoudre cet avertissement.

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 : évitez d'utiliser des modèles commençant par « % » dans les prédicats LIKE

Vous pouvez déclencher une analyse de table si vous utilisez une clause WHERE contenant un prédicat LIKE tel que « %pattern string » pour rechercher du texte pouvant figurer n'importe où dans une colonne.

Comment corriger les violations

Pour résoudre ce problème, vous devez modifier la chaîne de recherche de manière à ce qu'elle commence par un caractère qui n'est pas un caractère générique (%), ou vous devez créer un index de recherche en texte intégral.

Exemple

Dans le premier exemple, l'instruction SELECT déclenche une analyse de la table parce que la chaîne de recherche commence par un caractère générique. Dans le deuxième exemple, l'instruction déclenche une recherche d'index parce que la chaîne de recherche ne commence pas par un caractère générique. Une recherche d'index permet de récupérer uniquement les lignes qui correspondent à la clause 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 : déplacer une référence de colonne d’un côté d’un opérateur de comparaison pour utiliser un index de colonne

Votre code peut déclencher une analyse de table s'il compare une expression qui contient une référence à une colonne.

Comment corriger les violations

Pour résoudre ce problème, vous devez retravailler la comparaison de manière à ce que la référence à la colonne apparaisse seule d'un côté de l'opérateur de comparaison, au lieu d'être à l'intérieur d'une expression. Lorsque vous exécutez le code qui contient la référence de la colonne seule d'un côté de l'opérateur de comparaison, SQL Server peut utiliser l'index de la colonne et aucune analyse de table n'est effectuée.

Exemple

Dans la première procédure, une clause WHERE inclut la colonne [c1] dans une expression dans le cadre d'une comparaison. Dans la seconde procédure, les résultats de la comparaison sont identiques mais ne nécessitent jamais d'analyse de table.

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 : utiliser ISNULL(column, default_value) sur les colonnes nullables dans les expressions

Si votre code compare deux valeurs NULL ou une valeur NULL avec n'importe quelle autre valeur, il retourne un résultat inconnu.

Comment corriger les violations

Vous devez indiquer explicitement comment traiter les valeurs NULL dans les expressions de comparaison en enveloppant chaque colonne pouvant contenir une valeur NULL dans une fonction ISNULL.

Exemple

Cet exemple montre une définition de table simple et deux procédures stockées. La table contient une colonne, c2, qui peut contenir une valeur NULL. La première procédure, ProcedureWithWarning, compare c2 à une valeur constante. La deuxième procédure résout le problème en enveloppant c2 d'un appel à la fonction 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 : extraire les appels de fonction déterministes à partir des prédicats WHERE

Dans un prédicat WHERE, un appel de fonction est déterministe si sa valeur ne dépend pas des données sélectionnées. Ces appels peuvent entraîner des analyses inutiles des tables, ce qui réduit la performance de la base de données.

Comment corriger les violations

Pour résoudre ce problème, vous pouvez affecter le résultat de l'appel à une variable que vous utilisez dans le prédicat WHERE.

Exemple

Dans le premier exemple, la procédure stockée inclut un appel de fonction déterministe, ABS(@param1), dans le prédicat WHERE. Dans le deuxième exemple, une variable temporaire contient le résultat de l'appel.

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