163
6.1 Principes de l’indexation
nance. La mise à jour de colonnes incluses provoque des écritures dans l’index, et
potentiellement des splits de pages d’index lorsque la colonne est de taille variable.
Index filtré et contrainte d’unicité
Nous le savons, NULL n’est pas une valeur, c’est même le contraire d’une valeur : c’est
l’absence de valeur, l’inconnu. Comment gérer cet inconnu dans une contrainte
d’unicité ? La norme SQL indique en toute logique qu’une contrainte d’unicité doit
accepter de multiples marqueurs NULL. Dans la prise en charge par SQL de la logique
à trois états, le NULL est discriminant. Une requête comme :
SELECT *
FROM Person.Contact
WHERE Title = 'Mr.'
Les lignes dont le Title est NULL ne sont pas retournées. Ces lignes pourraient
correspondre à un Title = 'Mr.', mais nous n’en savons rien, nous ne pouvons donc
les considérer. Le même phénomène s’applique à l’unicité. Une colonne contenant
le marqueur NULL pourrait correspondre à une valeur déjà entrée, mais nous n’en
savons rien. Par conséquent, une contrainte d’unicité devrait accepter les NULL, et
remettre sa vérification au moment où la colonne est réellement alimentée d’une
valeur.
SQL Server ne réagit pas ainsi. Un seul marqueur NULL est accepté dans une contrainte d’unicité ou dans un index unique, sans doute en partie parce que, pour SQL
Server, NULL est une clé d’index comme une autre (une recherche WHERE … IS NULL
utilise l’index comme toute autre comparaison d’égalité). Pour gérer ce problème
nous avons, en SQL Server 2005, deux solutions : implémenter la contrainte à l’aide
d’un déclencheur, et donc nous passer de l’index unique, ou créer une colonne calculée persistée et indexée, basée sur la colonne à unifier, dans laquelle nous remplaçons
les marqueurs NULL par une valeur unique, par exemple calculée sur la clé primaire,
que nous garantissons différente de toute valeur possible de la colonne source. Cette
deuxième solution peut être intéressante dans certains cas, mais elle est un peu difficile à gérer, et elle augmente la taille des données.
En SQL Server 2008, une clause de filtre est introduite à la création d’index. Elle est intéressante pour notre cas, mais aussi pour optimiser des index sur des colonnes dont seules
quelques valeurs sont sélectives. Vous pouvez simplement ajouter une clause WHERE à la
commande de création d’index nonclustered :
CREATE UNIQUE INDEX uqf$Person_Contact$EmailAddress
ON Person.Contact (EmailAddress)
WHERE EmailAddress IS NOT NULL;
Les lignes qui ne correspondent pas à la clause WHERE ne sont simplement pas prises en
compte dans l’index. De fait, ce filtre nous permet d’implémenter un index unique répondant
à la norme SQL. La clause WHERE accepte les comparaisons simples, et l’utilisation du IN.
Mais la création d’index filtrés n’est pas limitée aux index uniques, vous pouvez
l’utiliser sur des colonnes très peu sélectives pour certaines valeurs et très sélectives
Précédent

- 175/334

Suivant