web-dev-qa-db-fra.com

Index avec colonnes incluses, quelle est la différence?

Je n'ai jamais vraiment compris la différence entre ces deux index, quelqu'un peut-il expliquer la différence (en termes de performances, à quoi ressemblera la structure d'index en db, en termes de stockage, etc.)?

Je comprends que cette question est large, veuillez me suivre. Je ne sais pas vraiment comment l'étendre. Peut-être que si vous commencez à expliquer vos savoir-faire, j'obtiendrai des pointeurs dans la bonne direction me permettant de rendre la question plus étroite?

Index inclus

CREATE NONCLUSTERED INDEX IX_Address_PostalCode  
ON Person.Address (PostalCode) 
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID); 

indice 'Normal'

CREATE NONCLUSTERED INDEX IX_Address_PostalCode  
ON Person.Address (PostalCode, AddressLine1, AddressLine2, City, StateProvinceID);
18
dadde

Le stockage interne des index utilise une structure B-Tree et se compose de "pages d'index" (la racine et toutes les pages intermédiaires) et de "pages de données d'index" (les pages feuilles uniquement).

Remarque: ne confondez pas les "pages de données d'index" avec les "pages de données" (pages feuilles d'index cluster) qui stockent la plupart des colonnes de données réelles.

  • Seules les colonnes d'index sont stockées sur les pages d'index.
  • En plaçant certaines colonnes dans la section INCLUDE, moins de données par clé d'index sont stockées sur chaque page.
  • Cela signifie que moins de pages sont nécessaires pour contenir les clés d'index. ( Faciliter plus longtemps la mise en cache de ces pages fréquemment utilisées en mémoire. )
  • Et peut-être moins de niveaux dans l'arbre. ( Dans un tel cas, les avantages en termes de performances peuvent être beaucoup plus importants car chaque parcours au niveau de l'arborescence est un autre accès au disque. )

Lorsqu'un index est utilisé, la clé d'index est utilisée pour parcourir les pages d'index jusqu'à la page de données d'index correcte.

  • Si l'index contient des colonnes INCLUDE, ces données sont immédiatement disponibles si la requête en a besoin.
  • Si la requête nécessite des colonnes non disponibles dans les clés d'index ou les colonnes INCLUDE, une "recherche de signet" supplémentaire est requise pour la ligne correcte dans l'index cluster (ou le tas si aucun index cluster n'est défini).

Certaines choses à noter qui, espérons-le, corrigent une partie de votre confusion:

  • Si les clés de votre index et les filtres de votre requête ne sont pas sélectifs , alors l'index sera ignoré (quel que soit le contenu de votre INCLUDE Colonnes).
  • Chaque index que vous créez a une surcharge pour les instructions INSERT et UPDATE; plus encore pour les index "plus gros". (Plus grand s'applique également aux colonnes INCLUDE.)
  • Ainsi, alors que vous pourriez en théorie créer une multitude de gros index avec des colonnes d'inclusion pour correspondre à toutes les permutations des chemins d'accès: ce serait très contre-productif.

Il convient de noter qu'avant l'ajout de INCLUDE colonnes en tant que fonctionnalité:

  • C'était une "astuce" de réglage d'index courante pour étendre les clés d'un index pour inclure les colonnes qui n'étaient pas nécessaires dans l'index/filtre. (Connu comme un indice de couverture.)
  • Ces colonnes étaient généralement requises dans les colonnes de sortie ou comme colonnes de référence pour les jointures à d'autres tables.
  • Cela éviterait les fameuses "recherches de signets", mais avait l'inconvénient de rendre l'indice "plus large" que strictement nécessaire.
  • En fait, très souvent, les colonnes antérieures de l'index identifient déjà une ligne unique ce qui signifie que les colonnes supplémentaires incluses seraient complètement redondantes sinon pour l'avantage "éviter les recherches de signets".
  • Les colonnes INCLUDE permettent essentiellement le même avantage plus efficacement.

NB Quelque chose de très important à signaler. En règle générale, vous n'obtenez aucun avantage des colonnes INCLUDE dans vos index si vous avez l'habitude paresseuse d'écrire toujours vos requêtes sous la forme SELECT * .... En retournant toutes les colonnes vous vous assurez en gros qu'une recherche de signet est requise dans tous les cas.

17
Disillusioned

Dans le premier index, dans Index page seulement PostalCode est la colonne clé et AddressLine1, AddressLine2, City, StateProvinceID font partie du nœud feuille pour éviter key/RID Chercher

Je préférerai le premier index lorsque ma table sera toujours filtrée sur PostalCode et l'une de ces colonnes AddressLine1, AddressLine2, City, StateProvinceID fera partie de select et non de la filtration

select AddressLine1, AddressLine2, City, StateProvinceID
from Person.Address 
Where PostalCode=  

Dans le deuxième index, dans Index page il y aura cinq colonnes clés PostalCode, AddressLine1, AddressLine2, City, StateProvinceID

Je préférerai le deuxième index quand j'ai la possibilité de filtrer des données comme

Where PostalCode = And AddressLine1 = 

ou

Where PostalCode = And AddressLine2 = 

ou

Where PostalCode = And AddressLine1  = and AddressLine2 = 

etc..

Dans tous les cas, la première colonne de l'index doit faire partie de la filtration pour utiliser l'indice

6
Pரதீப்

Dans le premier exemple, seule la colonne d'index: PostalCode est stockée dans l'arborescence d'index avec toutes les autres colonnes stockées au niveau feuille de l'index. Cela réduit la taille de l'index et est utile si vous n'utilisez pas un regroupement where, Join, par contre les autres colonnes, mais uniquement contre PostalCode.

Dans le deuxième index, toutes les données de toutes les colonnes sont stockées dans l'arborescence d'index, ce qui rend l'index beaucoup plus grand mais est utile si vous utilisez l'une des colonnes dans une instruction WHERE/JOIN/GROUP BY/ORDER By.

L'inclusion de colonnes accélère la récupération des données lorsqu'elles sont spécifiées dans la liste de sélection.

Par exemple, si vous exécutez:

SELECT PostalCode, AddressLine1, AddressLine2, City, StateProvinceID 
FROM Person.Address 
Where PostalCode= 'A1234'

Cela bénéficiera de la création d'un index sur PostalCode et de toutes les autres colonnes

En revanche, si vous exécutez:

SELECT PostalCode, AddressLine1, AddressLine2, City, StateProvinceID 
FROM Person.Address 
Where PostalCode= 'A1234' or City = 'London' or StateProvinceID = 1 or AddressLine1 = 'street A' or AddressLine2 = 'StreetB'

Il serait plus avantageux d'avoir toutes les colonnes de l'index

Jetez un œil aux liens ci-dessous, ceux-ci pourraient vous aider davantage avec votre requête

Index avec colonne incluse: https://msdn.Microsoft.com/en-us/library/ms190806 (v = sql.105) .aspx

Organisation des tables et des index: https://msdn.Microsoft.com/en-us/library/ms189051 (v = sql.105) .aspx

2
user7415753