265
8.3 Optimisation du code SQL
celle-ci : lorsque c’est possible, choisissez la syntaxe la plus « intuitive » et la plus
« traditionnelle ». La clarté aide l’optimiseur, et les syntaxes plus anciennes, bien
connues, ont plus de chance de bénéficier d’optimisations solides.
Comparaisons et filtres
Dans la clause WHERE d’une requête, comme dans la clause ON d’une jointure, peuvent
êtres exprimées des expressions de filtre. Ces expressions retournent un résultat en
logique ternaire : VRAI, FAUX ou INCONNU. Elles sont composées d’un opérateur et de deux opérandes (à gauche et à droite de l’opérateur). La plupart du temps,
un des opérandes au moins est une colonne de table. L’autre opérande est la valeur
recherchée. Par exemple :
SELECT LastName, FirstName
FROM Person.Contact
WHERE LastName LIKE 'Al%';
Si la colonne recherchée est indexée, l’optimiseur va peut-être choisir d’utiliser
l’index dans le plan d’exécution, selon la sélectivité de celui-ci. Si les estimations de
l’optimiseur lui montrent qu’un scan de la table ou d’un index sera moins coûteux en
lectures qu’une recherche dans les clés de l’index, le scan sera choisi. Cela dépend du
nombre de lignes retournées par la requête. Quoi qu’il en soit, en l’absence d’un
index utile, SQL Server sera obligé d’exécuter un scan. Considérez donc la création
d’index sur les colonnes présentes dans vos expressions de filtre, et testez après création si l’index est utilisé par la requête. Cette règle est bien entendu valable pour les
expressions de jointure :
SELECT c.LastName, c.FirstName, a.AddressLine1, a.PostalCode, a.City
FROM Person.Contact c
JOIN HumanResources.Employee e ON c.ContactId = e.ContactId
JOIN HumanResources.EmployeeAddress ea ON e.EmployeeId = ea.EmployeeId
JOIN Person.Address a ON ea.AddressId = a.AddressId;
Dans cet exemple, les expressions de la clause ON des jointure effectuent des
recherches sur les colonnes tout comme la clause WHERE. Elles bénéficient donc de la
présence d’index. Les clés des tables mères sont déjà indexées : en règle générale, une
jointure est effectuée entre une ou plusieurs colonnes liées par une contrainte de clé
étrangère (bien que rien dans le langage SQL ne force la jointure à s’appuyer sur une
telle définition de modèle). La clé étrangère ne peut s’appuyer que sur une clé primaire ou unique de la table mère. Ces clés créent nécessairement des index. Par
exemple, La colonne ContactId de la table Person.Contact est clé primaire clustered.
Par contre la création de clé étrangère en SQL Server ne force en rien la création
d’un index sur la clé déportée dans la table fille. C’est à vous de le faire, et c’est pratiquement une étape nécessaire pour assurer la bonne performance des requêtes de
jointure.
Pour qu’une expression de filtre utilise l’index, il est impératif que la colonne soit
présente comme opérande, sans aucune modification. C’est ce qu’on appelle un
SARG (Search ARGument). Un seek d’index ne peut être évalué comme possibilité
que sur un opérande de type SARG, c’est-à-dire qui correspond exactement à ce qui
8.3 Optimisation du code SQL
celle-ci : lorsque c’est possible, choisissez la syntaxe la plus « intuitive » et la plus
« traditionnelle ». La clarté aide l’optimiseur, et les syntaxes plus anciennes, bien
connues, ont plus de chance de bénéficier d’optimisations solides.
Comparaisons et filtres
Dans la clause WHERE d’une requête, comme dans la clause ON d’une jointure, peuvent
êtres exprimées des expressions de filtre. Ces expressions retournent un résultat en
logique ternaire : VRAI, FAUX ou INCONNU. Elles sont composées d’un opérateur et de deux opérandes (à gauche et à droite de l’opérateur). La plupart du temps,
un des opérandes au moins est une colonne de table. L’autre opérande est la valeur
recherchée. Par exemple :
SELECT LastName, FirstName
FROM Person.Contact
WHERE LastName LIKE 'Al%';
Si la colonne recherchée est indexée, l’optimiseur va peut-être choisir d’utiliser
l’index dans le plan d’exécution, selon la sélectivité de celui-ci. Si les estimations de
l’optimiseur lui montrent qu’un scan de la table ou d’un index sera moins coûteux en
lectures qu’une recherche dans les clés de l’index, le scan sera choisi. Cela dépend du
nombre de lignes retournées par la requête. Quoi qu’il en soit, en l’absence d’un
index utile, SQL Server sera obligé d’exécuter un scan. Considérez donc la création
d’index sur les colonnes présentes dans vos expressions de filtre, et testez après création si l’index est utilisé par la requête. Cette règle est bien entendu valable pour les
expressions de jointure :
SELECT c.LastName, c.FirstName, a.AddressLine1, a.PostalCode, a.City
FROM Person.Contact c
JOIN HumanResources.Employee e ON c.ContactId = e.ContactId
JOIN HumanResources.EmployeeAddress ea ON e.EmployeeId = ea.EmployeeId
JOIN Person.Address a ON ea.AddressId = a.AddressId;
Dans cet exemple, les expressions de la clause ON des jointure effectuent des
recherches sur les colonnes tout comme la clause WHERE. Elles bénéficient donc de la
présence d’index. Les clés des tables mères sont déjà indexées : en règle générale, une
jointure est effectuée entre une ou plusieurs colonnes liées par une contrainte de clé
étrangère (bien que rien dans le langage SQL ne force la jointure à s’appuyer sur une
telle définition de modèle). La clé étrangère ne peut s’appuyer que sur une clé primaire ou unique de la table mère. Ces clés créent nécessairement des index. Par
exemple, La colonne ContactId de la table Person.Contact est clé primaire clustered.
Par contre la création de clé étrangère en SQL Server ne force en rien la création
d’un index sur la clé déportée dans la table fille. C’est à vous de le faire, et c’est pratiquement une étape nécessaire pour assurer la bonne performance des requêtes de
jointure.
Pour qu’une expression de filtre utilise l’index, il est impératif que la colonne soit
présente comme opérande, sans aucune modification. C’est ce qu’on appelle un
SARG (Search ARGument). Un seek d’index ne peut être évalué comme possibilité
que sur un opérande de type SARG, c’est-à-dire qui correspond exactement à ce qui
