Question

J'ai plusieurs tables dont les seules données uniques sont une colonne uniqueidentifier (un Guid).Parce que les guids ne sont pas séquentiels (et qu'ils sont générés côté client, je ne peux donc pas utiliser newsequentialid()), j'ai créé un index non primaire et non clusterisé sur ce champ ID plutôt que de donner aux tables un index primaire clusterisé. clé.

Je me demande quelles sont les implications en termes de performances de cette approche.J'ai vu certaines personnes suggérer que les tables devraient avoir un int à incrémentation automatique (« identité ») comme clé primaire clusterisée même si cela n'a aucune signification, car cela signifie que le moteur de base de données lui-même peut utiliser cette valeur pour rapidement recherchez une ligne au lieu d’avoir à utiliser un signet.

Ma base de données est répliquée par fusion sur un groupe de serveurs, j'ai donc évité les colonnes d'identité int car elles sont un peu difficiles à réaliser lors de la réplication.

Quelles sont vos pensées?Les tables doivent-elles avoir des clés primaires ?Ou est-il acceptable de ne pas avoir d'index clusterisés s'il n'y a pas de colonnes raisonnables à indexer de cette façon ?

Était-ce utile?

La solution

Lorsque vous traitez des index, vous devez déterminer à quoi votre table va être utilisée.Si vous insérez principalement 1 000 lignes par seconde et n’effectuez aucune requête, un index clusterisé nuit aux performances.Si vous effectuez 1 000 requêtes par seconde, le fait de ne pas avoir d'index entraînera de très mauvaises performances.La meilleure chose à faire lorsque vous essayez d'ajuster les requêtes/index est d'utiliser l'analyseur de plan de requête et le profileur SQL dans SQL Server.Cela vous montrera où vous rencontrez des analyses de table coûteuses ou d'autres bloqueurs de performances.

En ce qui concerne l’argument GUID vs ID, vous pouvez trouver des personnes en ligne qui ne jurent que par les deux.On m'a toujours appris à utiliser les GUID, sauf si j'ai une très bonne raison de ne pas le faire.Jeff a un bon article qui explique les raisons de l'utilisation des GUID : https://blog.codinghorror.com/primary-keys-ids-versus-guids/.

Comme pour presque tout ce qui concerne le développement, si vous cherchez à améliorer les performances, il n’y a pas une seule bonne réponse.Cela dépend vraiment de ce que vous essayez d'accomplir et de la manière dont vous mettez en œuvre la solution.La seule vraie réponse est de tester, tester et tester à nouveau par rapport aux mesures de performances pour vous assurer que vous atteignez vos objectifs.

Modifier] @matt, après avoir fait plus de recherches sur le débat GUID / ID, je suis tombé sur ce post.Comme je l’ai déjà mentionné, il n’y a pas de vraie bonne ou de mauvaise réponse.Cela dépend de vos besoins spécifiques en matière de mise en œuvre.Mais voici quelques raisons tout à fait valables d’utiliser les GUID comme clé primaire :

Par exemple, il existe un problème connu sous le nom de « point chaud », dans lequel certaines pages de données d'un tableau sont soumises à un conflit de devises relativement élevé.Fondamentalement, ce qui se passe, c'est que la majeure partie du trafic sur une table (et donc les verrous au niveau de la page) se produit sur une petite zone de la table, vers la fin.Les nouveaux enregistrements seront toujours envoyés vers ce hotspot, car IDENTITY est un générateur de nombres séquentiels.Ces insertions sont gênantes car elles nécessitent un verrouillage de page exclusif sur la page à laquelle elles sont ajoutées (le hotspot).Cela sérialise efficacement toutes les insertions dans une table grâce au mécanisme de verrouillage des pages.NewID(), en revanche, ne souffre pas de points chauds.Les valeurs générées à l'aide de la fonction NewID() ne sont séquentielles que pour de courtes rafales d'insertions (où la fonction est appelée très rapidement, comme lors d'une insertion sur plusieurs lignes), ce qui provoque la répartition aléatoire des lignes insérées dans les pages de données de la table. de tout à la fin - éliminant ainsi un point chaud des insertions.

De plus, comme les insertions sont distribuées de manière aléatoire, le risque de fractionnement de pages est considérablement réduit.Même si une page divisée ici et là n’est pas trop grave, les effets s’additionnent rapidement.Avec IDENTITY, le facteur de remplissage de page est plutôt inutile en tant que mécanisme de réglage et pourrait tout aussi bien être réglé à 100 % - les lignes ne seront jamais insérées dans une page autre que la dernière.Avec NewID(), vous pouvez réellement utiliser Fill Factor comme outil d'amélioration des performances.Vous pouvez définir le facteur de remplissage sur un niveau qui se rapproche de la croissance estimée du volume entre les reconstructions d'index, puis planifier les reconstructions pendant les heures creuses à l'aide de la réindexation dbcc.Cela retarde efficacement les performances des fractionnements de pages jusqu'aux heures creuses.

Si même tu pense vous devrez peut-être activer la réplication pour la table en question - alors vous pourriez aussi bien faire du PK un identifiant unique et marquer le champ guid comme ROWGUIDCOL.La réplication nécessitera un champ guid à valeur unique avec cet attribut, et en ajoutera un s'il n'en existe pas.Si un champ approprié existe, il utilisera simplement celui qui s'y trouve.

Un autre avantage énorme de l'utilisation des GUID pour les PK est le fait que la valeur est effectivement garantie comme unique - pas seulement parmi toutes les valeurs générées par ce serveur, mais toutes les valeurs générées par tous ordinateurs - qu'il s'agisse de votre serveur de base de données, de votre serveur Web, de votre serveur d'applications ou de votre ordinateur client.Presque tous les langages modernes ont désormais la capacité de générer un guid valide - dans .NET, vous pouvez utiliser System.Guid.NewGuid.Ceci est TRÈS pratique lorsqu'il s'agit d'ensembles de données maître-détails mis en cache en particulier.Vous n'êtes pas obligé d'employer des systèmes de saisie temporaires fous simplement pour relier vos enregistrements avant qu'ils ne soient validés.Il vous suffit de récupérer un nouveau Guid parfaitement valide à partir du système d'exploitation pour la valeur de clé permanente de chaque nouvel enregistrement au moment de la création de l'enregistrement.

http://forums.asp.net/t/264350.aspx

Autres conseils

La clé primaire sert à trois fins :

  • indique que la ou les colonnes doivent être uniques
  • indique que la ou les colonnes doivent être non nulles
  • documenter l'intention qu'il s'agisse de l'identifiant unique de la ligne

Les deux premiers peuvent être spécifiés de nombreuses manières, comme vous l'avez déjà fait.

La troisième raison est bonne :

  • pour les humains, afin qu'ils puissent facilement voir votre intention
  • pour l'ordinateur, afin qu'un programme susceptible de comparer ou de traiter votre table puisse interroger la base de données pour connaître la clé primaire de la table.

Une clé primaire ne doit pas nécessairement être un champ numérique à incrémentation automatique, je dirais donc que c'est une bonne idée de spécifier votre colonne guid comme clé primaire.

Je me lance, parce que Matt m'a un peu harcelé.

Vous devez comprendre que même si un index clusterisé est placé par défaut sur la clé primaire d'une table, les deux concepts sont distincts et doivent être considérés séparément.Un CIX indique la manière dont les données sont stockées et référencées par les NCIX, tandis que le PK fournit un caractère unique pour chaque ligne afin de satisfaire aux exigences LOGIQUES d'une table.

Une table sans CIX n'est qu'un tas.Une table sans PK est souvent considérée comme « pas une table ».Il est préférable de comprendre séparément les concepts PK et CIX afin de pouvoir prendre des décisions judicieuses en matière de conception de base de données.

Rob

Personne n'a répondu à la vraie question :quels sont les avantages/inconvénients d'une table sans PK NI index CLUSTERED.À mon avis, si vous optimisez pour des insertions plus rapides (en particulier les insertions en masse incrémentielles, par ex.lorsque vous chargez des données en masse dans une table non vide), une telle table :sans index clusterisé, AUCUNE contrainte, AUCUNE clé étrangère, AUCUNE valeur par défaut et AUCUNE clé primaire, dans une base de données avec un modèle de récupération simple, est le meilleur.Maintenant, si jamais vous souhaitez interroger cette table (au lieu de l'analyser dans son intégralité), vous souhaiterez peut-être ajouter des index non uniques non clusterisés si nécessaire, mais les conserver au minimum.

Moi aussi, j'ai toujours entendu dire qu'avoir un int auto-incrémenté est bon pour les performances même si vous ne l'utilisez pas réellement.

Une clé primaire n'a pas besoin d'être un champ auto-incrémenté, dans de nombreux cas, cela signifie simplement que vous compliquez la structure de votre table.

Au lieu de cela, une clé primaire doit être la collection minimale d'attributs (notez que la plupart des SGBD autorisent une clé primaire composite) qui identifie de manière unique un tuple.

En termes techniques, il devrait s'agir du champ dont dépendent entièrement fonctionnellement tous les autres champs du tuple.(Si ce n'est pas le cas, vous devrez peut-être normaliser).

En pratique, des problèmes de performances peuvent signifier que vous fusionnez des tables et utilisez un champ incrémentiel, mais il me semble que je me souviens de quelque chose à propos de l'optimisation prématurée qui est mauvaise...

Puisque vous effectuez une réplication, vos identités correctes sont quelque chose à éviter.Je ferais de votre GUID une clé primaire mais non clusterisée puisque vous ne pouvez pas utiliser newsequentialid.Cela me semble être votre meilleur cours.Si vous n'en faites pas un PK mais que vous y mettez un index unique, tôt ou tard, cela peut amener les personnes qui maintiennent le système à ne pas comprendre correctement les relations FK, introduisant des bogues.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top