web-dev-qa-db-fra.com

L'index d'une colonne d'identité doit-il être non clusterisé?

Pour une table avec une colonne d'identité, un index PK/unique en cluster ou non en cluster doit-il être créé pour la colonne d'identité?

La raison en est que d'autres index seront créés pour les requêtes. Une requête qui utilise un index non cluster (sur un segment de mémoire) et renvoie des colonnes qui ne sont pas couvertes par l'index utilisera moins d'E/S logiques (LIO) car il n'y a pas d'étapes de recherche d'arborescence b d'index en cluster supplémentaires?

create table T (
  Id int identity(1,1) primary key, -- clustered or non-clustered? (surrogate key, may be used to join another table)
  A .... -- A, B, C have mixed data type of int, date, varchar, float, money, ....
  B ....
  C ....
  ....)

create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries

-- Common query is query on A, B, C, ....
select A, B 
from T 
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)

select A, B, C
from T 
where B between @a and @a+5 

....

PK en cluster sur la colonne d'identité est bon car:

  1. Il augmente de façon monotone afin qu'aucune page ne se divise lors de l'insertion. On dit qu'un insert en vrac peut être aussi rapide que sur une table en tas (non cluster)

  2. C'est étroit

Cependant, les requêtes dans la question seront-elles plus rapides sans la définir en cluster?

** Mise à jour: ** Que faire si le Id est le FK des autres tables et qu'il sera joint dans certaines requêtes?

19
u23432534

Par défaut, le PK est mis en cluster et dans la plupart des cas, c'est très bien. Cependant, quelle question devrait être posée:

  • mon PK doit-il être mis en cluster?
  • quelle (s) colonne (s) sera la meilleure clé pour mon index clusterisé?

PK et l'index cluster sont deux choses différentes:

  • PK est une contrainte. PK est utilisé pour identifier de manière unique les lignes, mais il n'y a aucune notion de stockage. Cependant, par défaut (dans SSMS), il est appliqué par un index cluster unique si un index cluster n'est pas encore présent.
  • Les index clusterisés sont un type d'index spécial qui stocke les données de ligne au niveau feuille, ce qui signifie qu'il est toujours couvrant. Toutes les colonnes, qu'elles fassent partie ou non de la clé, sont stockées au niveau feuille. Il n'est pas nécessaire qu'il soit unique, auquel cas un unificateur (4 octets) est ajouté à la clé en cluster.

Maintenant, nous nous retrouvons avec 2 questions:

  • Comment puis-je identifier de manière unique les lignes de ma table (PK)
  • Comment puis-je le stocker au niveau feuille d'un index (Clustered Index)

Cela dépend de la façon dont:

  • vous concevez votre modèle de données
  • vous interrogez vos données et vous écrivez vos requêtes
  • vous insérez ou mettez à jour vos données
  • ...

Tout d'abord, avez-vous besoin d'un index clusterisé? Si vous insérez en bloc, il est plus efficace de stocker des données non ordonnées dans un HEAP (par rapport aux données ordonnées dans un cluster). Il utilise le RID (Row Identifier, 8 octets) pour identifier de manière unique les lignes et les stocker sur des pages.

L'index cluster ne doit pas être une valeur aléatoire. Les données au niveau feuille seront stockées et ordonnées par la clé d'index. Par conséquent, il doit croître en permanence afin d'éviter la fragmentation ou le fractionnement de page. Si cela ne peut pas être réalisé par le PK, vous devez considérer une autre clé en tant que candidat en cluster. L'index clusterisé sur les colonnes identy, séquentiel GUID ou même quelque chose comme la date de l'insertion est très bien d'un point de vue séquentiel puisque toutes les lignes seront ajoutées à la dernière page feuille. En revanche, tandis que l'identifiant unique peut être utile aux besoins de votre entreprise en tant que PK, ils ne doivent pas être regroupés (ils sont commandés/générés de manière aléatoire).

Si, après quelques analyses de données et de requêtes, vous découvrez que vous utilisez principalement le même index pour obtenir vos données avant d'effectuer une recherche de clé dans le PK en cluster, vous pouvez le considérer comme un index en cluster bien qu'il ne puisse pas identifier de manière unique vos données.

La clé d'index cluster est composée de toutes les colonnes que vous souhaitez indexer. Une colonne uniquefier (4 octets) est ajoutée s'il n'y a pas de contrainte unique dessus (valeur incrémentielle pour les doublons, null sinon). Cette clé d'index sera ensuite stockée une fois pour chaque ligne au niveau feuille de tous vos index non cluster. Certains d'entre eux seront également stockés plusieurs fois à des niveaux intermédiaires (branche) entre la racine et le niveau feuille de l'arbre d'index (arbre B). Si la clé est trop grande, tout l'index non clusterisé s'agrandira, nécessitera plus de stockage et plus d'E/S, CPU, mémoire, ... Si vous avez un PK sur nom + date de naissance + pays, il est très probable que cette clé n'est pas un bon candidat. Il est trop grand pour un index clusterisé. Uniqueidentifier utilisant NEWSEQUENTIALID () n'est généralement pas considéré comme une clé étroite (16 octets) bien qu'il soit séquentiel.

Ensuite, une fois que vous avez compris comment identifier de manière unique les lignes de votre tableau, vous pouvez ajouter un PK. Si vous pensez que vous ne l’utiliserez pas dans votre requête, ne le créez pas en cluster. Vous pouvez toujours créer un autre index non cluster si vous avez parfois besoin de l'interroger. Notez que le PK créera automatiquement un index unique.

Les index non clusterisés contiendront toujours la clé clusterisée. Cependant, si les colonnes indexées (+ colonnes clés) couvrent, il n'y aura pas de recherche de clé dans l'index clusterisé. N'oubliez pas que vous pouvez également ajouter Inclure et Où à un index non cluster. (fais-en bon usage)

L'index cluster doit être unique et aussi étroit que possible. L'index cluster ne doit pas changer avec le temps et doit être inséré de manière incrémentielle.

Il est maintenant temps d'écrire du SQL qui créera la table, les index et les contraintes en cluster et non-cluster.

Tout cela est théorique car nous ne connaissons pas votre modèle de données et les types de données utilisés (A et B).

16
Julien Vavasseur

Pour une table avec une clé primaire (PK) sur une colonne d'identité, elle sera groupée par défaut. Pourrait-il être mieux que non cluster?

Si vous demandez si la valeur par défaut pour une clé primaire sur une colonne d'identité (en particulier) ne doit pas être mise en cluster, je dirais non. La plupart des tables ont l'avantage d'avoir un index clusterisé, donc faire du clustering la valeur par défaut pour une contrainte de clé primaire est probablement globalement utile, en particulier pour les nouveaux utilisateurs de SQL Server.

Comme avec à peu près n'importe quelle option, il existe toujours des circonstances différentes dans lesquelles l'une doit être préférée à l'autre, mais un administrateur de base de données expérimenté doit être conscient de la valeur par défaut et pouvoir la remplacer le cas échéant. Voir aussi les questions et réponses connexes, Quand une clé primaire doit-elle être déclarée non clusterisée? .

Les requêtes dans la question seront-elles plus rapides sans la mettre en cluster?

Oui, mais avec des mises en garde.

Les recherches RID sont en effet plus efficaces que les recherches de clés. Même si toutes les pages requises sont en mémoire (très probablement pour les niveaux supérieurs d'un index), il y a un coût CPU associé à la navigation dans l'arborescence b de l'index clusterisé. Par conséquent, SQL Server peut généralement effectuer beaucoup plus de recherches RID que de recherches de clés par unité de temps CPU.

Avertissements

Ce qui précède ne serait pas souvent un facteur déterminant pour décider de structurer une table comme un tas ou non. Il devrait être impossible d'éviter les recherches (en utilisant des index de couverture), et le nombre de recherches devrait être suffisamment important pour avoir un effet mesurable (et important) sur les performances, compte tenu de l'environnement matériel et de la charge de travail.

Il n'est pas vraiment pratique de couvrir tous les aspects du débat tas vs index clusterisé dans cette réponse, mais je dirai qu'il y a relativement peu de bonnes raisons de préférer structurer une table comme un tas en général. Pour moi, le choix du type de conception proposé dans la question nécessiterait une analyse très approfondie avant la mise en œuvre et devrait respecter une barre très élevée. Des arguments généraux sur "l'évolutivité" ne seraient pas suffisants.

Concernant la mise à jour de la question sur les jointures, l'évaluation de l'impact de la perte de l'index cluster sur les plans d'exécution ferait partie de l'analyse mentionnée ci-dessus. Si des jointures de boucles imbriquées sont utilisées, il est très pratique d'avoir l'index clusterisé sur la clé de jointure car toutes les colonnes de la ligne sont immédiatement disponibles sans recherche.

Ma propre expérience a été que le fait d'avoir des index clusterisés uniques sur les colonnes d'identité est très souvent bénéfique, tout est pris en compte. J'ai trouvé des tas problématiques en termes de gestion de l'espace, et je dois également mentionner que certaines fonctionnalités de SQL Server nécessitent un index cluster unique pour fonctionner.

11
Paul White 9

En fait, vous n'avez pas besoin de créer d'index cluster ni de clé primaire, car les index uniques et les index non uniques peuvent gérer le travail. SQL Server prend en charge un index clusterisé depuis au moins la version 1.1, mais la clé primaire n'est qu'un "concept" que les programmeurs appliquent en définissant un index unique.

Mais il semble que les clés primaires et les index cluster sont des concepts précieux dans la majorité des bases de données.

Examinons la documentation de SQL Server pour voir les descriptions partielles de certaines options d'indexation comme indiqué ci-dessous.

Index clusterisé: https://msdn.Microsoft.com/en-us/library/ms190457.aspx

  • Les index clusterisés trient et stockent les lignes de données dans la table ou la vue en fonction de leurs valeurs clés. Ce sont les colonnes incluses dans la définition d'index.
  • Il ne peut y avoir qu'un seul index clusterisé par table

Clé primaire: https://msdn.Microsoft.com/en-us/library/ms190457.aspx

  • Une table ne peut contenir qu'une seule contrainte PRIMARY KEY.

  • Toutes les colonnes définies dans une contrainte PRIMARY KEY doivent être définies comme NOT NULL.

  • La clé primaire peut être créée en tant qu'index cluster (par défaut s'il n'y a pas d'index cluster) ou index non cluster.

Index unique: https://msdn.Microsoft.com/en-us/library/ms187019.aspx

  • Lorsque vous créez une contrainte UNIQUE, un index non cluster unique est créé pour appliquer une contrainte UNIQUE par défaut.

  • Vous pouvez spécifier un index cluster unique si un index cluster n'existe pas déjà pour la table.

Cela signifie que votre question sur les index en cluster et les clés primaires concerne vraiment certains des problèmes suivants. Veuillez noter que toutes les tables ne bénéficient pas du même plan d'indexation.

Quand bénéficierais-je de la séparation de la clé primaire de l'index cluster?

Peut-être lorsque l'index clusterisé est large (par exemple, 5 colonnes d'informations textuelles, mais la clé primaire est petite (INT ou BIGINT), comme vous semblez le décrire.

  • Un large index clusterisé vous permettrait de sélectionner rapidement des lignes dans l'index pour un sous-ensemble de requêtes qui fournissent des réponses en série à partir de index clusterisé (également connu sous le nom de Tableau ). Par exemple, un index clusterisé à 5 colonnes prendrait en charge le balayage des colonnes C1, C2, C3, C4, C5 ou C1, C2, C3, C4 et ainsi de suite jusqu'à C1.
  • Remarque: Si les lignes sont volumineuses, cela peut vous apporter des avantages en termes de vitesse de sélection de l'ensemble de lignes série, en particulier si d'autres colonnes du tableau sont régulièrement incluses dans l'ensemble de résultats.
  • Dans ce cas, vous pouvez utiliser la clé primaire pour l'intégrité référentielle afin de fournir la valeur requise en tant que clé étrangère pour contraindre les lignes dans d'autres tables. Le PK est petit et est donc le FK est un petit coup sur la taille des tables référencées.
  • Cependant, notez que tout index créé sur une table qui a un index cluster inclura toutes les colonnes de cluster dans les autres index que vous créez sur cette table. Un large index clusterisé augmenterait la taille de tous les index non clusterisés de cette table.

Devriez-vous faire de la clé primaire seule l'index cluster?

  • Si vous avez une petite clé primaire (INT ou BIGINT) et qu'il s'agit de l'index clusterisé, la surcharge des colonnes du cluster est relativement petite. Bien que la clé primaire en cluster dans ce cas existera également dans chaque index de cette table, c'est un prix plus bas à payer que le cluster large décrit ci-dessus.

  • Cet index clusterisé de clé primaire n'offre généralement pas directement un moyen facile de sélectionner plusieurs lignes en série.

  • Maintenant que vous avez créé une clé primaire en cluster, qu'en est-il des autres colonnes que vous étiez autrefois envisagez d'inclure dans l'index en cluster?

  • Créez un index unique (ou non unique) selon les besoins pour indexer ce large critère de recherche des colonnes C1, C2, C3, C4, C5. Les valeurs de cet index "Imitation Clustered" peuvent servir de chemin de recherche plus rapide pour ces 5 colonnes. S'il existe également une ou deux colonnes non indexées qui sont régulièrement sélectionnées, elles peuvent être incluses dans l'index avec INCLUDE (Doctor_Name, Diagnosis_Synopsis).

Bien que je trouve les index clusterisés simples et les clés primaires utiles, il existe de bonnes raisons de réfléchir à leur utilisation dans une table ou dans une base de données.

Avez-vous besoin d'un index clusterisé?

  • Si vous créez des index (index uniques et index non uniques) et définissez la clé primaire sans surcharger d'être un index clusterisé, vous pourriez constater que les index plus étroits vous fournissent ce dont vous avez besoin pour vos requêtes.

  • Il existe certains comportements utiles dans les index clusterisés et les clés primaires, mais n'oubliez pas que ce sont vraiment les index qui importent le plus. Concevez la stratégie d'indexation pour prendre en compte les réalités de votre application. Peut-être que OneBigTable doit avoir une stratégie d'indexation différente de celle que vous utilisez pour la plupart des tables.

  • Sans un index clusterisé, vos données seront stockées sous la forme d'un tas avec l'identificateur de ligne (RID) qui n'est pas du tout un bon mécanisme de recherche. Mais, comme mentionné précédemment, vous pouvez créer des index uniques et non uniques pour gérer vos requêtes.

Ce qui vous amène maintenant à considérer les tas:

Tas et index: https://msdn.Microsoft.com/en-us/library/hh213609.aspx

  • Lorsqu'une table est stockée en tant que segment de mémoire, les lignes individuelles sont identifiées par référence à un identificateur de ligne (RID) composé du numéro de fichier, du numéro de la page de données et de l'emplacement sur la page. L'identifiant de ligne est une structure petite et efficace. (Mais ce n'est pas un index .)
  • Parfois, les architectes de données utilisent des tas lorsque les données sont toujours accessibles via des index non clusterisés et que le RID est plus petit qu'une clé d'index cluster .

Mais si vous avez également des "points chauds" dans un ensemble de données volumineuses, vous pouvez également rechercher un autre type d'index:

Index filtré: https://msdn.Microsoft.com/en-us/library/cc280372.aspx

  • Un index filtré bien conçu améliore les performances des requêtes et la qualité du plan d'exécution car il est plus petit qu'un index non cluster de table complète et possède des statistiques filtrées. Les statistiques filtrées sont plus précises que les statistiques de table complète car elles ne couvrent que les lignes de l'index filtré .

  • Les index filtrés ont un certain nombre de restrictions qui sont décrites dans le lien vers les index filtrés.

Cependant, si vous êtes intéressé à penser à cette possibilité de sauter les clés primaires et les index clusterisés, vous pouvez lire le post de Markus Winand lié ci-dessous. Il démontre ses raisons, avec quelques exemples de code, pour suggérer que ce serait parfois une bonne idée de renoncer à utiliser ces fonctionnalités.

http://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key

Mais tout revient finalement à comprendre votre application et à concevoir le code, les tables, les index, etc. pour s'adapter au travail que vous faites.

8
RLF