Vous partagez une séquence de clés primaires unique dans une base de données?

14

Est-ce une pratique acceptable d'utiliser une seule séquence comme clé primaire dans toutes les tables (au lieu qu'une clé primaire soit unique pour une table donnée, elle est unique pour toutes les tables)? Si tel est le cas, est-il objectivement préférable à l'utilisation d'une seule séquence de clés primaires entre les tables.

Je suis un développeur de logiciels junior, pas un administrateur de base de données, donc j'apprends encore bon nombre des bases d'une bonne conception de base de données.

Edit: au cas où quelqu'un se poserait la question, j'ai récemment lu une critique de la conception d'une base de données par l'un des administrateurs de base de données de notre entreprise qui a mentionné que le design n'utilisait pas une seule clé primaire dans toute la base de données, ce qui semblait différent de ce que J'ai appris jusqu'ici.

Edit2: Pour répondre à une question dans les commentaires, c'est pour Oracle 11g, mais je me demandais à un niveau non spécifique à la base de données. Si cette question dépend de la base de données, je serais intéressé de savoir pourquoi, mais dans un tel cas, je chercherais une réponse spécifique à Oracle.

Lawtonfogle
la source
2
C'est généralement une idée terrible, pour des raisons de performances.
Philᵀᴹ
1
En fait, il y a un plus grand avantage à avoir chaque table avec sa propre plage de clés primaires indépendante. Mais seulement en ce que lorsque vous regardez un tas d'ID, vous pouvez dire que celui-ci est des comptes, celui-ci est PurchaseHeader, etc. (Oui, j'ai travaillé avec un système comme celui-ci, il y a de nombreuses années.)
RLF
Quel SGBD utilisez-vous? Oracle? Postgres? DB2?
a_horse_with_no_name
1
Est-il possible que vous ayez mal interprété ce qu'il voulait dire? Peut-être qu'il n'était pas aussi littéral?
JamesRyan
La société DBA signifie-t-elle réellement qu'aucun champ de clé primaire n'est présent dans aucune des tables?
Max Vernon

Réponses:

13

Acceptable? Sûr. Commun? Non. Bénéfique? Douteux.

Lors de mon ancien travail, nous avons hérité d'un système où ils avaient un générateur de séquence central (il s'agissait d'un système SQL Server bien avant SEQUENCEson introduction dans SQL Server 2012). Ce n'était pas vraiment un goulot d'étranglement des performances et ne devrait pas l'être, sauf si vous générez des centaines de milliers de valeurs par seconde. Mais cela a rendu tout le code beaucoup plus complexe qu'il ne devait l'être, sans raison valable. Le but de la conception était de s'assurer que si quelque chose dans le système se voyait attribuer une valeur ID de 12, une seule chose dans le système pouvait avoir l'ID 12. Cela me semblait assez obtus et je ne l'ai jamais compris. Si j'ai un client avec CustomerID = 12, pourquoi cela m'empêche-t-il d'avoir une commande avec OrderID = 12?

Je vois l'utilité d'un générateur de séquence central si vous avez plusieurs systèmes et que vous générez des identifiants pour un certain type d'entité (par exemple, un client ou une commande) à partir de ces multiples systèmes. Une séquence centrale peut distribuer de nouvelles valeurs à plusieurs systèmes sans être un goulot d'étranglement (juste un seul point de défaillance) et sans craindre que deux systèmes génèrent le même ID.

Aaron Bertrand
la source
Si vous deviez choisir entre quelque chose comme ça et simplement utiliser des identifiants uniques comme clés primaires, auriez-vous une préférence (bien que la réponse soit probablement "cela dépend")? Il semble qu'un GUID contournerait le problème de la même manière, sauf que vous obtiendriez une implémentation standard plutôt que d'avoir à lancer votre propre générateur de clé primaire centralisé. De toute évidence, l'utilisation d'une séquence dans SQL 2012 accomplirait les deux choses, mais en supposant que quelqu'un se trouve sur une version plus ancienne?
SqlRyan
2
@SqlRyan J'aurais besoin de comprendre pourquoi un OrderID doit être complètement distinct d'un CustomerID. Je n'utiliserais certainement pas un GUID pour cela; la configuration des plages d'IDENTITÉ pourrait être meilleure (les clients commencent à 1, les commandes commencent à 1000000, etc.) avec des alertes en place lorsque vous êtes sur le point d'épuiser la plage, bien sûr.
Aaron Bertrand
1
@SqlRyan - l'utilisation d'un GUID mal implémenté comme clé primaire en cluster peut provoquer toutes sortes de problèmes. Comme l'a dit Aaron, l'IDENTITÉ correspond bien mieux à l'objectif.
Max Vernon
Dans un système précédent, j'ai vu utiliser une seule séquence dans toute la base de données, cela a été fait pour permettre à une clé étrangère de pointer vers de nombreuses tables différentes au lieu d'une seule table, de sorte que lorsque vous avez dit que la clé étrangère de deux lignes différentes étaient 12, vous saviez qu'ils pointaient vers la même chose sans avoir besoin de vérifier sur quelle table possible ils pointaient. Un 13 dans la même colonne pourrait potentiellement être la clé primaire sur une table différente. Personnellement, je suis très mal à l'aise avec ce style de conception.
Lawtonfogle
@AaronBertrand Ou utilisez également des identifiants entiers simples et ajoutez du code au début lorsqu'ils sont en contact avec le client. par exemple. I1337, C1337 clairement une facture ou un client
JamesRyan
7

L'idée a du mérite dans une base de données très complexe où les gens pourraient accidentellement se joindre à une table en utilisant la mauvaise colonne et obtenir des lignes invalides simplement parce que les ID INT sont les mêmes.

Nous avons choisi d'avoir des GUID séquentiels comme clés primaires afin d'éviter certains des pièges de fragmentation d'index des GUID. Malheureusement, ils sont assez grands.

Le serveur SQL peut générer des GUID séquentiels via un appel par défaut de la fonction newSequentialID (), il n'y a donc pas de table de clés émises à maintenir et pas de goulot d'étranglement de blocage.

Cela nous a donné des ID uniques sur l'ensemble des bases de données, sur l'ensemble de notre entreprise, car ils sont vraiment uniques.

Le prix est bien sûr l'espace et sa problématique lorsque vous essayez de transférer les données vers un entrepôt de données / cube où la vitesse / la taille est basée sur l'utilisation de petites clés entières.

Je suis convaincu que nous avons évité de nombreux bugs dans notre application suite à leur utilisation.

RayG
la source
4

Je ne peux pas imaginer quelle pourrait être la raison de la séquence unique sur toutes les tables. Il ne fait que créer un goulot d'étranglement lors de la génération de nouvelles valeurs.

Quelle que soit la taille de la surcharge de génération de valeurs de clé séquentielle, le générateur est une ressource unique dont l'accès doit être synchronisé. Plus il reçoit de demandes, plus les chances que certains demandeurs attendent leur tour au robinet sont élevées. Il est évident que le générateur de séquence unique partagé entre toutes les tables sera accessible plus fréquemment par plus de clients, produisant ainsi plus de conflits, que n'importe lequel des générateurs multiples. L'affirmation peut devenir plus prononcée si les règles métier imposent des contraintes sur les valeurs générées, telles que l'absence de lacunes ou un ordre strict, ou dans une base de données en cluster.

Même avec le générateur de séquence le plus efficace, il y aura une charge de travail qui causera des conflits intolérables.

mustaccio
la source
2
Vous voudrez peut-être ajouter des détails sur la façon dont le goulot d'étranglement est créé et pourquoi c'est une mauvaise idée.
Max Vernon
2

le but de PrimaryKey dans les tables de base de données est principalement d'imposer l'unicité des données supposées uniques, car tous les flux de travail ne peuvent pas être couverts et garantissent qu'ils n'entraîneront pas de duplication des données. La deuxième raison est que, souvent, PK est également le principal candidat pour l'index clusterisé sur la table, ce qui stimule également la récupération des données lorsque / où ces colonnes sont correctement utilisées dans la requête de sélection.

l'utilisation d'un numéro de séquence comme clé primaire est la même que chaque table a une colonne d'identité et seule cette colonne est utilisée dans PrimaryKey. avoir un numéro de séquence unique dans la base de données doit avoir une utilisation spécifique, mais du point de vue de PrimaryKey, je ne comprends pas la raison. Par exemple, dans l'un des projets Datawarehouse sur lequel j'ai travaillé, nous avons une colonne appelée LoadBatchID et d'ETL à signaler que 50% de tous les tableaux ont cette colonne mais à certains endroits, elle a une signification différente. nous avons utilisé le proc unique comme générateur de nombres pour nous assurer que nous ne trouvons pas de conflits et nous aidons également à retrouver le fichier d'origine d'où proviennent les données et ce qui se passe à chaque étape d'ETL.

Anup Shah
la source
2

Je suppose qu'une raison de le faire serait que toutes les entités héritent d'une entité parent. Disons par exemple que vous vouliez pouvoir mettre un commentaire sur tout type d'entité:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Habituellement, cela ne se fait pas. .

Je ne connais pas les caractéristiques de performance.

Neil McGuigan
la source