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:
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)
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?
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:
PK et l'index cluster sont deux choses différentes:
Maintenant, nous nous retrouvons avec 2 questions:
Cela dépend de la façon dont:
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).
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.
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.
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
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.
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
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.