Quand une clé primaire doit-elle être déclarée en cluster?

169

Lors de la création d'une base de données de test pour une autre question que j'avais posée précédemment, je me suis souvenu de la possibilité de déclarer une clé primaire. NONCLUSTERED

Quand utiliseriez-vous une NONCLUSTEREDclé primaire par opposition à une CLUSTEREDclé primaire?

Merci d'avance

Stuart Blackler
la source

Réponses:

188

La question n'est pas de savoir quand le PK doit être un NC, mais plutôt de demander quelle est la clé appropriée pour l'index clusterisé.

Et la réponse dépend vraiment de la manière dont vous interrogez les données . L'index clusterisé a un avantage sur tous les autres index: puisqu'il inclut toujours toutes les colonnes, il couvre toujours. Par conséquent, les requêtes pouvant exploiter l'index clusterisé n'ont certainement pas besoin d'utiliser des recherches pour satisfaire certaines des colonnes et / ou prédicats projetés.

Une autre pièce du puzzle consiste à savoir comment utiliser un index . Il existe trois modèles typiques:

  • sondes, lorsqu'une seule valeur de clé est recherchée dans l'index
  • analyses de plage, lorsqu'une plage de valeurs de clé est récupérée
  • ordre par exigence, quand un index peut satisfaire un ordre sans nécessiter un tri aller-retour

Par conséquent, si vous analysez votre charge attendue (les requêtes) et découvrez qu'un grand nombre de requêtes utiliseraient un index particulier parce qu'elles utilisent un certain modèle d'accès bénéficiant d'un index, il est logique de proposer cet index en tant qu'index clusterisé.

Un autre facteur réside dans le fait que la clé d'index cluster est la clé de recherche utilisée par tous les index non cluster. Par conséquent, une clé d'index cluster étendue crée un effet d'entraînement et élargit tous les index non clusterisés. , plus de mémoire, moins de bonté.

Un bon index clusterisé est stable , il ne change pas pendant la durée de vie de l'entité, car une modification des valeurs de la clé d'index cluster signifie que la ligne doit être supprimée et réinsérée.

Et un bon index clusterisé grandit dans un ordre non aléatoire (chaque valeur de clé nouvellement insérée est plus grande que la valeur précédente) afin d'éviter les fractionnements de page et la fragmentation (sans déconner avec FILLFACTORs).

Alors, maintenant que nous savons ce qu'est une bonne clé d'index cluster, la clé primaire (qui est une propriété logique de modélisation de données) correspond-elle aux exigences? Si oui, alors la PK devrait être groupée. Si non, alors la PK ne devrait pas être en cluster.

Pour donner un exemple, considérons un tableau de données de vente. Chaque entrée a un identifiant qui est la clé primaire. Mais la grande majorité des requêtes demandent des données entre une date et une autre date. Par conséquent, la meilleure clé d'indexation en cluster serait la date de vente et non l' ID . Un autre exemple d’index clusterisé différent de la clé primaire est une clé de sélectivité très faible, telle qu’une «catégorie» ou un «état», une clé avec très peu de valeurs distinctes. Avoir une clé d'index cluster avec cette clé de sélectivité faible comme clé la plus à gauche, par exemple (state, id), a souvent du sens en raison des balayages de plages qui recherchent toutes les entrées dans un «état» particulier.

Une dernière remarque sur la possibilité d’une clé primaire non clusterisée sur un segment de mémoire (c’est-à-dire qu’il n’existe aucun index clusterisé). Il peut s'agir d'un scénario valide. La raison typique est que les performances des insertions en bloc sont essentielles, car les tas ont un débit de insertion en bloc nettement supérieur à celui des index clusterisés.

Remus Rusanu
la source
1
Que signifie "ordre par exigences, lorsqu'un index peut satisfaire un ordre sans nécessiter un tri par arrêt" signifie ici?
Mike Sherrill 'Cat Recall'
2
@RemusRusanu. +1 réponse très utile. Une question concernant l'exemple (state, id). Dans cet exemple, l'exigence "le bon index clusterisé croît de manière non aléatoire" ne sera pas satisfaite, n'est-ce pas? Alors peut-on le considérer comme un bon index clusterisé?
LCJ
26

La raison fondamentale pour utiliser les index clusterisés est indiquée sur Wikipedia :

La mise en grappes modifie le bloc de données dans un certain ordre distinct pour correspondre à l'index, ce qui entraîne le stockage des données de ligne dans l'ordre. Par conséquent, un seul index en cluster peut être créé sur une table de base de données donnée. Les index clusterisés peuvent augmenter considérablement la vitesse globale de récupération, mais généralement uniquement lorsque les données sont accédées de manière séquentielle dans le même ordre inverse ou inversement de l'index clusterisé , ou lorsqu'une plage d'éléments est sélectionnée.

Dites que j'ai une table de personnes et que ces personnes ont une colonne Pays et une clé primaire unique. C'est un tableau démographique, alors ce sont les seules choses qui me tiennent à cœur. quel pays et combien de personnes uniques sont liées à ce pays.

Je ne suis donc susceptible de ne jamais sélectionner que où ou ordre par la colonne pays; un index en cluster sur la clé primaire ne me fait aucun bien, je n'accède pas à ces données par PK, je les accède par cette autre colonne. Étant donné que je ne peux avoir qu'un seul index clusterisé sur une table, déclarer ma PK en tant que cluster m'empêcherait d'utiliser un index clusterisé sur un pays.

En outre, voici un bon article sur les index clusterisés et non clusterisés : il s'avère que les index clusterisés causaient des problèmes de performances d'insertion dans SQL Server 6.5 (ce qui, espérons-le, n'est pas pertinent pour la plupart d'entre nous ici).

Si vous placez un index clusterisé sur une colonne IDENTITY, toutes vos insertions se produiront sur la dernière page de la table - et cette page est verrouillée pour la durée de chaque IDENTITY. Pas de problème ... sauf si vous avez 5000 personnes qui veulent toutes la dernière page. Ensuite, vous avez beaucoup de conflits pour cette page

Notez que ce n'est pas le cas dans les versions ultérieures.

Ben Brocka
la source
3
FIY, vous avez mentionné SQL Server 6.5: dba.stackexchange.com/questions/1584/...
GBN
15

Si votre clé primaire est du UNIQUEIDENTIFIER, assurez-vous de spécifier que c'est NONCLUSTERED. Si vous le faites en cluster, chaque insertion devra faire un tas de remaniement d'enregistrements pour insérer la nouvelle ligne à la position correcte. Ce sera la performance du réservoir.

Bryan Johns
la source
1
Bien que j'essaie d'éviter les UUID pour les clés en cluster, je pense que le raisonnement ci-dessus peut être incomplet. Le serveur SQL ne remanie pas nécessairement les lignes pour insérer un dans la position correcte (si vous voulez dire "entre les valeurs inférieure et supérieure"). Envisagez une insertion au milieu d'un trillion de tables. Une indirection supplémentaire est nécessaire, ce qui peut être ce que vous vouliez dire. Un UNIQUEIDENTIFIERtype séquentiel existe également et a la même probabilité de générer des clés uniques, bien qu'il souffre toujours d'une taille de 128.
Charles Burns
8

Un exemple très courant:

  • Customertable avec CustomerIDcommeCLUSTERED PRIMARY KEY
  • Table de commande avec OrderID (PK), CustomerID, OrderDateet quelques autres colonnes
  • OrderPositions avec OrderPositionID (PK), OrderId, ProductID, Amount, Price ...
  • vous devez indexer les tables d'ordre

Bien sûr, "ça dépend" est - comme presque toujours - la bonne réponse, mais la plupart des applications (pas BI-Reports) fonctionneront selon le client (par exemple, vous vous connectez en tant que client 278 sur le site Web et cliquez sur "Mes commandes" ou le commis liste toutes les commandes du client 4569 ou votre routine de facturation récapitulera toutes les commandes du client 137).

Dans ce cas, il n’aurait pas beaucoup de sens de regrouper la table en fonction du format OrderID. Oui, vous aurez des questions SELECT ... WHERE OrderId = ?concernant la liste des détails de la commande, mais il s’agit généralement d’une recherche courte et peu coûteuse (3 lectures).

D'un autre côté, si vous souhaitez classer votre Ordertable en cluster CustomerID, il ne serait pas nécessaire d'effectuer plusieurs recherches de clé à chaque fois que vous interrogez la table CustomerId = ?.

Le CLUSTERED INDEXdoit toujours être UNIQUE, sinon SQL Server ajouterait invisible (= inutilisable) colonne INT UNIQUIFIERpour assurer la uniquiness - et il serait beaucoup plus logique d'ajouter des données réelles (utilisables) puis des choses au hasard ( en fonction de l'ordre d'insertion).

Parce qu'un client passera (espérons-le) plus d'une commande, nous devrons ajouter soit le OrderIDou (si vous triez habituellement pour cela) le OrderDate(s'il s'agit d'une date / heure - sinon le client serait limité à une commande par jour) à le CLUSTERED INDEXet se retrouver avec:

CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)

Les mêmes règles s'appliquent à la OrderPositionstable. Habituellement , la plupart des requêtes listera toutes les positions pour le ordre spécifique, vous devez donc créer le PK avec l' OrderPositionIDen NONCLUSTEREDet UNIQUE CLUSTERED INDEXsur OrderId, OrderPositionID.

BTW: il est correct que la Customertable soit groupée par son PK (le CustomerID, parce que c'est une "table de premier niveau") et sera, dans une application typique, principalement interrogée par son code client.

Les tables de recherche pures, par exemple Gendersou, InvoiceTypesou PaymentTypesont un autre exemple de table qui devrait être mise en cluster par sa PK (parce que vous les joindrez habituellement sur GenderId, InvoiceTypeIdou PaymentTypeId).

Thomas Franz
la source
2

Lorsqu'un index en cluster est jugé plus bénéfique pour l'ensemble du système qu'un PK en cluster en utilisant une mesure de performance. Il ne peut y avoir qu'un seul index clusterisé sur une table.

Les exemples de mesures de performances sont le temps d'interrogation simple (vitesse), l'intégration des temps d'interrogation totaux par rapport à la table (efficacité) et l'obligation d'ajouter de nombreuses colonnes include à un très grand index non clusterisé afin d'obtenir des performances similaires à celles d'un cluster (taille). ).

Cela peut se produire lorsque les données sont généralement extraites à l'aide d'un index non unique, contenant des valeurs NULL (non autorisées dans une clé PK) ou si la clé PK a été ajoutée pour une raison secondaire (telle que la réplication ou l'identification des enregistrements de suivi d'audit).

crokusek
la source