Index non cluster manquant faisant déjà partie de l'index cluster

9

Je débogue une requête à exécution lente et dans le plan d'exécution, un index non cluster est suggéré, avec un impact de 51,6648. Toutefois, l'index non clusterisé inclut uniquement les colonnes qui se trouvent déjà dans l'index composite composite de clé primaire (PK).

Serait-ce à cause de l'ordre des colonnes dans l'index? c'est-à-dire que si les colonnes de l'index cluster ne sont pas dans l'ordre du plus sélectif au moins, y a-t-il un potentiel pour un index non clusterisé d'améliorer les performances?

De plus, l'index non clusterisé ne contient que deux des trois colonnes PK, la troisième étant ajoutée en tant que colonne incluse. Est-ce includeune autre raison pour laquelle l'utilisation de l'index non clusterisé pourrait être plus optimale?

Voici un exemple des structures de table avec lesquelles je travaille:

Les tables-

Retailers (
    RetailerID int PK, 
    name ...)

Retailer_Relation_Types (
    RelationType smallint PK, 
    Description nvarchar(50) ...)

Retailer_Relations (
    RetailerID int PK FK, 
    RelatedRetailerID int PK FK, 
    RelationType smallint PK FK, 
    CreatedOn datetime ...)

Le tableau Retailer_Relationsprésente l'indice PK composite suivant et l'index suggéré.

CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX <NameOfIndex> 
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )
Fletch
la source

Réponses:

12

La table Retailer_Relations a l'index composite PK suivant et l'index suggéré-

Alors que les index manquants pourraient être utiles et pourraient certainement fonctionner, je ne passerais pas trop de temps sur les index manquants, ces conseils sont créés sur le plan d'exécution estimé, pas sur le plan d'exécution réel.

Plus précisément, ces indices sont basés sur l'hypothèse de réduction du coût des Query Bucks ™ utilisés par les opérateurs du plan. L'optimiseur calcule les coûts estimés et ajoute les indices d'index manquants en conséquence.

En conséquence, ils pourraient se tromper. Si vous ne savez pas si cela va vous aider, la meilleure chose à faire est de tester la situation avant et après. Vous pouvez le faire en ajoutant l'instruction SET STATISTICS IO, TIME ON;avant d'exécuter la requête.

En outre, vous pouvez utiliser l' analyseur de statistiques pour faciliter la lecture de ces statistiques.

Serait-ce à cause de l'ordre des colonnes dans l'index?

C'est exact, la création de l'index manquant peut améliorer la sélectivité des requêtes, par exemple si votre requête ressemble à ceci:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

ou comme ça:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

Le raisonnement derrière cela est que les deux indices pourraient rechercher sur RetailerID, cette partie ne va pas changer. Mais que se passe-t-il si des filtres / commandes supplémentaires sont appliqués sur RelationType? Il serait partout dans l'index clusterisé, car il s'agit de la troisième valeur de clé, pas de la deuxième valeur de clé. Et comme nous le savons, c'est la deuxième valeur clé du NCI.

D'accord, mais quand ou comment l'index non cluster pourrait-il améliorer la requête?

Quelques cas pourraient être:

  • Si relationType filtre un grand nombre de valeurs, les E / S résiduelles peuvent être élevées, ce qui pourrait nécessiter l'index non cluster (Requête n ° 1)
  • L'ordre sur les deux colonnes se produit (dans un sens) et l'ensemble de résultats est volumineux (requête n ° 2).
  • Comme l'a mentionné @AaronBertrand: si la différence de taille du CI par rapport au NCI est considérable, l'ajout du NCI réduira les pages lues par les requêtes qui en bénéficient.

NCI Side note

En remarque, l'ajout des colonnes de clés à la liste d'inclusion dans votre NCI n'est pas exactement nécessaire, car les colonnes de clés CI sont automatiquement incluses dans tous les index non clusterisés.

Vous pouvez choisir de le faire si vous n'êtes pas sûr si l'index clusterisé restera le même et que vous souhaitez que la colonne soit toujours incluse.

En ce qui concerne la requête elle-même, si vous avez ajouté le plan d'exécution via PasteThePlan, nous pourrions donner plus d'informations sur l'indexation / l'amélioration de la requête.


Essai

Créer un tableau et ajouter quelques lignes

CREATE TABLE Retailer_Relations (
    RetailerID int , 
    RelatedRetailerID int , 
    RelationType smallint, 
    CreatedOn datetime,
    CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY])


    DECLARE @I Int = 1
    WHILE @I < 1000
    BEGIN
    INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
    VALUES(@I,@I,@I,GETDATE()
    )
    set @I += 1
    END

Requête n ° 1

    SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

Plan sans index ici

Pendant qu'il effectue une recherche, il effectue une recherche sur RetailerID. Ensuite, il émet un prédicat d'E / S résiduel sur RelationType

Ajouter l'index

CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )

Le prédicat résiduel a disparu, tout se passe dans un prédicat de recherche, sur les deux colonnes.

Plan d'exécution

Avec la deuxième requête, la valeur d'aide de l'index ajouté devient encore plus évidente:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

Planifiez sans l'index, avec un opérateur de tri:

entrez la description de l'image ici

Planifier avec l'index, l'utilisation de l'index supprime l'opérateur de tri

entrez la description de l'image ici

Randi Vertongen
la source
1
Merci Randi, je vais marquer cela comme la réponse, mais je voulais simplement vous demander. Dites-vous que la suggestion d'index manquant est basée sur le plan d'exécution estimé? Je pose cette question car elle est affichée dans le plan d'exécution réel dans SS2016.
Fletch
1
Je me demandais si c'était ce que vous disiez, merci de la clarification.
Fletch