Question

Il existe un débat sain entre les clés de substitution et les clés naturelles:

SO Message 1

SO Post 2

Mon avis, qui semble correspondre à la majorité (c’est une faible majorité), est que vous devez utiliser des clés de substitution, à moins qu’une clé naturelle ne soit tout à fait évidente et qu’elle ne garantisse pas de modification. Ensuite, vous devez imposer l'unicité de la clé naturelle. Ce qui signifie des clés de substitution presque tout le temps.

Exemple des deux approches, en commençant par une table d'entreprise:

1: Clé de substitution: la table a un champ ID qui est la PK (et une identité). Les noms de société doivent être uniques par État, il y a donc une contrainte unique.

2: Clé naturelle: la table utilise CompanyName et State comme PK - satisfait à la fois la PK et son caractère unique.

Supposons que la société PK est utilisée dans 10 autres tables. Mon hypothèse, sans chiffres à l'appui, est que l'approche par clé de substitution serait beaucoup plus rapide ici.

Le seul argument convaincant que j'ai vu pour la clé naturelle concerne une table plusieurs-à-plusieurs qui utilise les deux clés étrangères comme clé naturelle. Je pense que dans ce cas, cela a du sens. Mais vous pouvez avoir des problèmes si vous avez besoin de refactoriser; c'est hors de propos de ce post je pense.

Quelqu'un a-t-il déjà vu un article comparant les différences de performances sur un ensemble de tableaux utilisant des clés de substitution contre , le même ensemble de tableaux utilisant touches naturelles ? En regardant autour de nous et Google n'a rien rapporté qui vaille la peine, juste beaucoup de théorie.

Mise à jour importante : j'ai déjà créé un ensemble de tables de test répondant à cette question. Cela ressemble à ceci:

  • PartNatural - Table des pièces utilisant le numéro de pièce unique en tant que PK
  • PartSurrogate - table des pièces qui utilise un identifiant (int, identité) en tant que PK et a un index unique sur le PartNumber
  • Plant - ID (int, identité) en tant que PK
  • Ingénieur - ID (int, identité) en tant que PK

Chaque pièce est jointe à une usine et chaque cas d’une pièce d’une usine est associé à un ingénieur. Si quelqu'un a un problème avec ce banc d'essai, c'est le moment.

Était-ce utile?

La solution

Utilisez les deux! Les clés naturelles empêchent la corruption de la base de données (incohérence pourrait être un meilleur mot). Lorsque le " right " la clé naturelle (pour éliminer les lignes en double) fonctionnerait mal en raison de la longueur ou du nombre de colonnes impliquées, une clé de substitution peut également être ajoutée pour être utilisée comme clé étrangère dans d'autres tables au lieu de la clé naturelle. Mais la clé naturelle doit rester une clé alternative ou un index unique pour éviter la corruption des données et améliorer la cohérence de la base de données ...

Une grande partie de la hoohah (dans le "débat" sur cette question) peut être due à une fausse hypothèse: vous devez utiliser la clé primaire pour les jointures et les clés étrangères dans les autres tables. C'EST FAUX. Vous pouvez utiliser N'IMPORTE QUELLE clé comme cible pour les clés étrangères dans d'autres tables. Il peut s'agir de la clé primaire, d'une clé alternative ou de tout index unique ou contrainte unique. Et en ce qui concerne les jointures, vous pouvez utiliser n'importe quoi pour une condition de jointure, il n'est même pas nécessaire que ce soit une clé, un idex ou même un élément unique! (bien que s'il n'est pas unique, vous obtiendrez plusieurs lignes dans le produit cartésien qu'il crée).

Autres conseils

La valeur des clés naturelles est différente de celle des clés de substitution, pas du type.

Tout type peut être utilisé pour une clé de substitution, comme un VARCHAR pour le slug généré par le système ou autre chose.

Cependant, les types les plus utilisés pour les clés de substitution sont INTEGER et RAW (16) (ou quel que soit le type utilisé par votre SGBDR pour GUID 's),

La comparaison d'entiers de substitution et d'entiers naturels (comme SSN ) prend exactement le même temps.

En comparant les VARCHAR , les collations sont prises en compte et elles sont généralement plus longues que les entiers, ce qui les rend moins efficaces.

La comparaison d'un ensemble de deux INTEGER est probablement également moins efficace que la comparaison d'un seul INTEGER .

Sur les types de données de petite taille, cette différence correspond probablement à pour cent de pourcentage du temps nécessaire pour récupérer des pages, des index de cheminement, des verrous de base de données, etc.

Et voici les chiffres (dans MySQL ):

CREATE TABLE aint (id INT NOT NULL PRIMARY KEY, value VARCHAR(100));
CREATE TABLE adouble (id1 INT NOT NULL, id2 INT NOT NULL, value VARCHAR(100), PRIMARY KEY (id1, id2));
CREATE TABLE bint (id INT NOT NULL PRIMARY KEY, aid INT NOT NULL);
CREATE TABLE bdouble (id INT NOT NULL PRIMARY KEY, aid1 INT NOT NULL, aid2 INT NOT NULL);

INSERT
INTO    aint
SELECT  id, RPAD('', FLOOR(RAND(20090804) * 100), '*')
FROM    t_source;

INSERT
INTO    bint
SELECT  id, id
FROM    aint;

INSERT
INTO    adouble
SELECT  id, id, value
FROM    aint;

INSERT
INTO    bdouble
SELECT  id, id, id
FROM    aint;

SELECT  SUM(LENGTH(value))
FROM    bint b
JOIN    aint a
ON      a.id = b.aid;

SELECT  SUM(LENGTH(value))
FROM    bdouble b
JOIN    adouble a
ON      (a.id1, a.id2) = (b.aid1, b.aid2);

t_source est simplement une table factice avec 1 000 000 lignes.

aint et unique , bint et bdouble contiennent exactement les mêmes données, sauf que aint a un entier sous la forme PRIMARY KEY , tandis que adouble contient une paire de deux entiers identiques.

Sur ma machine, les deux requêtes s'exécutent pendant 14,5 secondes, +/- 0,1 seconde

La différence de performance, le cas échéant, se situe dans la plage de fluctuations.

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