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
- SR0005 : évitez d'utiliser des modèles commençant par « % » dans les prédicats LIKE
- 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
- SR0007 : utiliser ISNULL(column, default_value) sur les colonnes nullables dans les expressions
- SR0015 : extraire les appels de fonction déterministes à partir des prédicats WHERE
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