Raisons de ne pas utiliser un nombre auto-incrémenté pour une key primaire

Je travaille actuellement sur la database de quelqu'un d'autre où les keys primaires sont générées via une table de search qui contient une list de noms de tables et la dernière key primaire utilisée. Une procédure stockée incrémente cette valeur et vérifie qu'elle est unique avant de la renvoyer au SP 'insert' appelant.

Quels sont les avantages pour utiliser une méthode comme celle-ci (ou simplement générer un GUID) au lieu de simplement utiliser le numéro d'identité / auto?

Je ne parle pas de keys primaires qui signifient réellement quelque chose comme des ISBN ou des codes de produit, mais simplement des identifiants uniques.

Merci.

Un identifiant généré automatiquement peut causer des problèmes dans les situations où vous utilisez la réplication (comme je suis sûr que les techniques que vous avez trouvées peuvent le faire!). Dans ces cas, j'opte généralement pour un GUID.

Si vous n'êtes pas susceptible d'utiliser la réplication, un PK auto-incrémentant fonctionnera probablement très bien.

Il n'y a rien de mal à utiliser AutoNumber, mais il y a quelques raisons de ne pas le faire. Pourtant, rouler sa propre solution n'est pas la meilleure idée, comme l'a mentionné Dacracot. Laisse-moi expliquer.

La première raison pour ne pas utiliser AutoNumber sur chaque table est que vous pouvez finir par merge des loggings de plusieurs tables. Imaginons que vous disposiez d'une table Sales Order et d'un autre type de table de commands, et que vous décidiez d'extraire des données communes et d'utiliser plusieurs inheritances de table. C'est bien d'avoir des keys primaires uniques au monde. Ceci est similaire à ce que Bobwienholt a dit à propos de la fusion de bases de données, mais cela peut se produire dans une database.

Deuxièmement, d'autres bases de données n'utilisent pas ce paradigme, et d'autres paradigmes tels que les séquences d'Oracle sont bien meilleurs. Heureusement, il est possible d'imiter les séquences Oracle en utilisant SQL Server. Une façon de procéder consiste à créer une table AutoNumber unique pour l'set de votre database, appelée MainSequence, ou autre. Aucune autre table de la database n'utilisera autonumber, mais toute personne ayant besoin d'une key primaire générée automatiquement utilisera MainSequence pour l'get. De cette façon, vous obtenez toutes les performances embeddedes, le locking, la security des threads, etc. dont dacracot parlait sans avoir à le build vous-même.

Une autre option consiste à utiliser des GUID pour les keys primaires, mais je ne le recommand pas car même si vous êtes sûr qu'un humain (même un développeur) ne les lira jamais, quelqu'un le fera probablement, et c'est difficile. Et plus important encore, les choses transtypées implicitement en T-SQL très facilement, mais peuvent avoir beaucoup de mal à implémenter un GUID. Fondamentalement, ils sont gênants.

Dans la construction d'un nouveau système, je recommand d'utiliser une table dédiée pour la génération de key primaire (tout comme les séquences Oracle). Pour une database existante, je ne ferais pas mon possible pour la changer.

de CodingHorror :

GUID Pros

  • Unique sur chaque table, chaque database, chaque server
  • Permet la fusion facile d'loggings de différentes bases de données
  • Permet une dissortingbution facile des bases de données sur plusieurs servers
  • Vous pouvez générer des ID n'importe où, au lieu d'avoir à faire un tour dans la database
  • La plupart des scénarios de réplication nécessitent des colonnes GUID de toute façon

GUID Cons.

  • C'est un énorme 4 fois plus grand que la valeur d'index traditionnelle de 4 octets; cela peut avoir de sérieuses implications en termes de performances et de stockage si vous ne faites pas attention
  • Généreux à déboguer (où userid = '{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Les GUID générés doivent être partiellement séquentiels pour de meilleures performances (par exemple, newsequentialid () sur SQL 2005) et permettre l'utilisation d'index clusterisés

L'article fournit beaucoup de bons liens externes sur la prise de décision sur GUID vs Auto Increment. Si je peux, je vais avec GUID.

La méthode de procédure d'incrémentation doit être thread-safe. Sinon, vous ne pouvez pas get des numéros uniques. En outre, il doit être rapide, sinon ce sera un goulot d'étranglement de l'application. Les fonctions embeddedes ont déjà pris en count ces deux facteurs.

Il est utile que les clients puissent pré-allouer tout un tas d'ID pour effectuer un encart en masse sans avoir à mettre à jour leurs objects locaux avec les ID insérés. Ensuite, il y a toute la question de la réplication, comme mentionné par Galwegian.

Mon problème principal avec les keys auto-incrémentées est qu'elles n'ont aucun sens

À mon avis, c'est une exigence d'une key primaire – n'avoir aucune autre raison d'exister que d'identifier un document. S'il n'a pas de signification dans le monde réel, alors il n'a aucune raison réelle de changer. Vous ne voulez pas que les keys primaires changent, en général, parce que vous devez searchr-replace votre database entière ou pire. J'ai été surpris par le genre de choses que j'ai supposé être uniques et immuables et qui ne se sont pas révélées être des années plus tard.

L'utilisation d'identifiants uniques vous permet de merge des données provenant de deux bases de données différentes.

Peut-être que vous avez une application qui recueille des données dans plusieurs bases de données, puis "synchronise" avec une database principale à différents moments de la journée. Vous ne devez pas vous inquiéter des collisions de key primaire dans ce scénario.

Ou, éventuellement, vous voudrez peut-être savoir quel sera l'identifiant d'un logging avant de le créer.

Un avantage est que cela peut permettre à la database / SQL d'être plus multiplateforme. Le SQL peut être exactement le même sur SQL Server, Oracle, etc …

Voici la chose avec incrémentation automatique des entiers en tant que keys:

Vous devez avoir publié l'logging avant d'y avoir access. Cela signifie que tant que vous n'avez pas publié l'logging, vous ne pouvez pas, par exemple, préparer des loggings associés qui seront stockés dans une autre table, ou l'une des nombreuses raisons possibles pour lesquelles il est utile d'accéder à l'logging unique. id, avant de l'afficher.

Ce qui précède est mon facteur décisif, que ce soit pour aller avec une méthode, ou l'autre.

La seule raison que je peux penser est que le code a été écrit avant que les sequences ont été inventées et le code a oublié de rattraper;)

Je préférerais utiliser un GUID pour la plupart des scénarios dans lesquels la méthode actuelle de la publication a du sens pour moi (la réplication étant possible). Si la réplication était le problème, une telle procédure stockée devrait être au courant de l'autre server qui devrait être lié pour assurer l'unicité de la key, ce qui le rendrait très fragile et probablement une mauvaise façon de le faire.
Une situation où j'utilise des keys primaires entières qui ne sont PAS des identités auto-incrémentées est le cas des tables de search rarement modifiées qui appliquent des contraintes de key étrangère, qui auront une énumération correspondante dans l'application consommasortingce de données. Dans ce scénario, je souhaite m'assurer que le mappage d'énumération sera correct entre le développement et le deployment, en particulier s'il y aura plusieurs servers prod.

Une autre raison possible est que vous voulez délibérément des keys randoms. Cela peut être souhaitable si, par exemple, vous ne voulez pas que les browsers fouineurs parcourent chaque élément de la database, mais ce n'est pas assez important pour justifier des mesures de security d'authentification.

La seule vraie raison de faire ceci est d'être agnostique à la database (si différentes versions db utilisent des techniques de numérotation automatique différentes).

L'autre problème mentionné ici est la possibilité de créer des loggings dans plusieurs endroits (comme dans le bureau central ainsi que sur les ordinateurs portables des users itinérants). Dans ce cas, cependant, vous auriez probablement besoin de quelque chose comme un "sitecode" unique à chaque installation qui était préfixé à chaque ID.

Un avantage secondaire utile de l'utilisation d'une key primaire GUID au lieu d'une key auto-incrémentée est que vous pouvez assigner la valeur PK pour une nouvelle ligne du côté client (en fait vous devez le faire dans un scénario de réplication), vous épargnant tracas de récupérer le PK de la ligne que vous venez d'append sur le server.

L'un des inconvénients d'un PK GUID est que les jointures sur un champ GUID sont plus lentes (sauf si cela a changé récemment). Un autre avantage de l'utilisation des GUID est qu'il est amusant d'essayer d'expliquer à un responsable non technique pourquoi une collision GUID est plutôt improbable.

La réponse de Galwegian n'est pas nécessairement vraie.

Avec MySQL, vous pouvez définir un décalage de key pour chaque instance de database. Si vous combinez cela avec un incrément assez grand, ça ira pour l'amende. Je suis sûr que d'autres fournisseurs auraient une sorte de parameters similaires.

Disons que nous avons 2 bases de données que nous voulons répliquer. Nous pouvons le configurer de la manière suivante.

 increment = 2 db1 - offset = 1 db2 - offset = 2 

Cela signifie que

db1 aura les touches 1, 3, 5, 7 ….

DB2 aura les touches 2, 4, 6, 8 ….

Par conséquent, nous n'aurons pas d'accrochage de key sur les inserts.

Mon problème principal avec les keys auto-incrémentées est qu'elles n'ont aucun sens.

Pour les tables où certains champs fournissent l'unicité (seule ou en combinaison avec une autre), j'opterais pour l'utiliser à la place.