Colonnes d'identité ou UDF qui génère explicitement un identifiant unique?

11

Je suis au milieu d'un débat sur la question de savoir s'il est préférable de créer une PRIMARY KEYcolonne d' identité , ou une UDF qui génère explicitement un identifiant unique.

  • Je plaide pour la colonne d'identité.
  • Mon partenaire plaide pour la génération manuelle des valeurs, affirme-t-il
    • en mettant l'UDF sur une autre table où nous pouvons avoir un UDF
      • verrouiller la ressource
      • incrémenter une table ID avec un champ appelé ID_Valuepar1
      • l'utiliser comme identifiant unique global
    • Ou demandez à la table de faire un id+1lors de l'insertion
    • Qu'il est plus simple de déplacer des données entre des serveurs et / ou des environnements n'ayant pas la contrainte d'identification; passer d'une base de données contenant des données à une autre base de données similaire avec, par exemple, des données intermédiaires ou factices. Pour les tests en dehors de la production, nous souhaitons peut-être retirer tous les enregistrements d'hier jusqu'à la mise en scène pour les tests.

Quelle mise en œuvre est la plus logique?

kacalapy
la source

Réponses:

21

Votre collègue est un idiot.

La solution ne sera pas évolutive, l'UDF n'est pas simultanée ( même raison que cela ). Et comment gérez-vous les insertions à plusieurs lignes: cela nécessiterait un appel UDF par ligne

Et la migration vers d'autres SGBDR ne se produit pas souvent dans la vraie vie ... vous pouvez tout aussi bien ne pas utiliser SQL Server maintenant et utiliser des séquences sur Oracle et espérer que vous ne migrez pas.

Éditer:

Votre mise à jour indique que le déplacement de données sert à actualiser des bases de données hors production.

Dans ce cas, vous ignorez les colonnes d'identité lors de l'actualisation. Vous ne compromettez pas votre implémentation pour faciliter le chargement sans prod. Ou utilisez des tables temporaires pour suivre les changements de valeur d'identité.

Ou utilisez des processus: nous actualisons notre système de test tous les soirs de la production, ce qui évite complètement le problème. (Et garantit que notre sauvegarde prod peut également être restaurée)

gbn
la source
11

Utilisez une valeur d'identité. La génération de votre propre table de séquence et de vos valeurs de séquence prendra beaucoup de temps et entraînera beaucoup de verrouillage et de blocage lors de la tentative de génération de nombres.

L'identité existe pour une raison, utilisez-la.

Lorsque SQL Denali sortira, il prendra en charge des séquences qui seront plus efficaces que l'identité, mais vous ne pouvez pas créer vous-même quelque chose de plus efficace.

En ce qui concerne le déplacement des enregistrements d'un environnement à un autre, activez IDENTITY_INSERT lors de l'insertion ou cochez la case dans SSIS.

mrdenny
la source
Si vous passez de la «production» au «test» et que vous avez un champ d'identité, vous courez le risque d'écraser ou de heurter des données. C'est tout ce que je dis. Oui, cela ne devrait pas être un problème dans cette direction, mais je dis simplement que cela pourrait arriver.
jcolebrand
Certes, vous aurez le même nombre pour différentes valeurs de ligne dans dev, test, qa, uat et production. Et alors? Si ces valeurs sont importantes (comme pour une table de recherche), codez-les manuellement, ce qui ne devrait pas être un problème car vous ne devriez pas mettre de valeurs dans ces tables très souvent. Si vous devez contrôler les valeurs d'identité entre les environnements pour éviter les collisions, réinitialisez les valeurs d'identité entre les environnements lorsque vous effectuez une restauration à partir de la production.
mrdenny
5

La colonne d'identité me semble bien. Je ne suis pas sûr de suivre la logique expliquant pourquoi il est difficile de déplacer des données entre les serveurs.

Si vous voulez que chaque ligne ait une identité globale unique, vous pouvez utiliser un UUID mais je ne le ferais pas à moins que vous ne soyez sûr que l'unicité globale est nécessaire - généralement ce n'est pas le cas. L'utilisation des UUID comme identifiants diminuera les performances, augmentera l'espace disque requis et rendra le débogage plus difficile - en raison de la longueur, il est difficile de se souvenir d'un UUID, de le dire à quelqu'un par téléphone ou de l'écrire sur papier sans erreur.

Mark Byers
la source
4

Pour les identifiants numériques simples, choisissez simplement l'identité et oubliez tous les problèmes liés à leur génération manuelle.

Vous pouvez toujours créer une "super table" qui utilise une identité comme PK et avoir une colonne de type et toute autre information. Lorsque vous avez besoin d'un nouvel ID (en supposant que vous voulez dire un IDS unique sur différentes tables), insérez simplement dans cette table et saisissez SCOPE_IDENTITY()puis insérez dans la table réelle dont vous avez besoin.

Fondamentalement, vous créez une table: MasterID avec une identité PK, lorsque vous devez insérer une ligne dans votre Table1, INSERT INTO MasterIDset obtenir l'identité générée par cette ligne à l'aide SCOPE_IDENTITY(), puis insérer dans Table1 en utilisant cette valeur comme PK.

Table1 aura un PK int non-identité. Vous feriez le même processus pour insérer dans Table2, etc. Laissez SQL Server gérer les valeurs d'identité dans la table MasterIDs , que vous pouvez ensuite utiliser dans vos autres tables. Les MasterID peuvent contenir d'autres tables, comme le type (vous pouvez donc savoir quelle table, Table1 ou Table2, etc., utilise cette valeur d'identité.

Paul White 9
la source
3

Tant que vous utilisez correctement les contraintes de clé étrangère (cascade, mise à jour, etc.), vous pourrez utiliser un champ d'identité. Je ne vois vraiment aucun avantage à l'autre solution dans ce cas.

Joe Phillips
la source
2

L'identité a été faite pour s'adapter à votre scénario. Vous disposez d'outils tels que la réplication pour l'échange de données serveur / environnements qui permettent de tout garder ensemble.


la source
1

Je viens de terminer un travail où j'ai remplacé une identitycolonne SQL Server par un intchamp normal et contrôlé l'allocation des ID moi-même.

J'ai vu des gains de performances assez impressionnants. Contrairement à l'OP, je n'ai pas d'UDF pour générer l'identifiant. Mais le principe est à peu près le même: il y a une partie du logiciel qui maintient un pool d'identifiants. Lorsqu'ils sont épuisés, il obtient un autre lot en interrogeant la base de données pour la prochaine valeur Low et l'incrémente au prochain High .

Cela nous permet de générer des identifiants et de relier toutes les entités en dehors d'une transaction dans notre ORM avant de soumettre les lots à la base de données et de soumettre également des lots plus importants sans aller-retour supplémentaires pour obtenir l'identité juste insérée (requis par les colonnes d'identité).

Dans la table id que nous avons, il y a plus d'une ligne, ce qui nous permet d'utiliser des plages spécifiques si nous le souhaitons. c'est-à-dire pour réutiliser des blocs supprimés et des identifiants négatifs.

marque
la source
0

J'utilise l'identité depuis des années et envisage sérieusement de remplacer le numéro d'identité par UNIQUEIDENTIFIER. C'est un cauchemar lorsque vous devez modifier le type de données si quelqu'un l'a conçu pour être une base de données compacte et un cauchemar si vous devez ajouter une identité à une colonne, vous ne pouvez pas non plus mettre à jour la colonne d'identité. Imaginez que vous mettez un entier et que votre base de données dépasse les 2 milliards d'enregistrements, encore une fois cauchemar pour changer (pensez aux FK)! Changer quoi que ce soit avec l'identité est un cauchemar et n'est pas à l'échelle, sauf si vous mettez bigint! UNIQUEIDENTIFIER vs Identity = commodité et robustesse vs amélioration des performances peut-être perceptible (n'a pas fait le benchmark).

Mise à jour: Après avoir vu cela, je penche définitivement vers UNIQUEIDENTIFIER. Cela ne montre aucun avantage réel de l'identité bigint et un tas d'avantages pour UNIQUEIDENTIFIER! Différentes versions de SQL Server peuvent avoir un résultat différent. Il y a simplement de la beauté à avoir un identifiant unique dans toutes les bases de données et tous les systèmes (robustesse)! Déplacez, copiez, transformez les données à votre guise! https://www.mssqltips.com/sqlservertip/5105/sql-server-performance-comparison-int-versus-guid/

Hrvoje Batrnek
la source
Un INT 64 bits durera très longtemps ...
Vérace