Question

J'ai récemment migré toute ma base de données de myisam vers innodb. Je suis assez nouveau dans tout cela, alors j’ai une question concernant l’utilisation de la clé étrangère.

Disons que j'ai deux tables: les utilisateurs et les messages.

utilisateurs

id (pr_key)
nom

messages

id (pr_key)
id_utilisateur
message

Les champs id sont tous les deux incrémentés automatiquement.

Alors maintenant, dans mes requêtes, je joins déjà ces 2 tables. Est-il encore nécessaire de placer une clé étrangère ici, je ne vois pas de point. At-il des avantages en termes de performances?

Si je choisis de mettre une clé étrangère ici, je suppose que je dois créer le pr_key des messages id et user_id.

  

L'ajout de l'autre prim_key ne prendra pas seulement plus d'espace, ce qui ralentira les performances.

     

Maintenant, si la table a deux pr_keys, et que je ne demande que sur l’une d’elles, aurai-je les mêmes avantages en termes de performances. Ou dois-je utiliser explicitement les deux clés?

Je sais que dans cet exemple, je rechercherai user_id. Il est donc peut-être judicieux de l'indexer de toute façon. Mais que se passe-t-il si le champ est un champ sur lequel il n'y a pas de recherche? Est-il toujours bon de placer une clé primaire multiple sur ce champ, uniquement pour la relation étrangère?

Merci!

Était-ce utile?

La solution

Il présente les avantages de l'intégrité des données .

cela empêchera le code de l'application d'entrer l'utilisateur_id de 1234 dans la table de messages lorsqu'il n'y a pas d'utilisateur avec id = 1234 dans la table d'utilisateurs. Et cela empêchera l'application de supprimer l'utilisateur lorsque l'utilisateur a des messages dans la table des messages.

Le nom de la PK ne doit pas nécessairement correspondre au nom de FK dans la table enfant de référence.

"Si je choisis de mettre une clé étrangère ici, je suppose que je dois créer le pr_key des messages id et user_id. "

NON . Vous ne modifiez pas la clé dans la table des messages, vous établissez simplement une contrainte de clé étrangère (FK) sur la colonne User_Id de la table des messages, qui référence (pointe vers) la colonne id de la table des utilisateurs. Aucune PK supplémentaire n'est requise dans les messages, et comme la PK est déjà unique (vous ne pouvez pas avoir deux messages avec le même messageId), la PK à la fois sur id et user_id ne peut plus ajouter d'unicité.

En résumé, vous pouvez avoir une idée fausse fondamentale sur ce que sont réellement une clé primaire et une clé étrangère.

  • Une PK est une contrainte sur l'unicité d'une ligne, elle nécessite un index.
  • Un FK est une contrainte sur la valeur d'une colonne (il spécifie que la valeur existe en tant que valeur PK dans une autre table référencée). Elle ne pas nécessite un index.

@Noah, consultez cette autre question SO

Autres conseils

Que vous établissiez ou non une règle FOREIGN KEY formelle sur les messages (user_id), le fait est qu’il s’agit d’une relation de clé étrangère.

Tout d’abord, rappelez-vous qu’une clé primaire appropriée sur une table devrait suffire à identifier de manière unique chaque enregistrement de la table. Étant donné que chaque message contient déjà le champ id , vous ne souhaitez pas non plus insérer le id_utilisateur dans la clé primaire de la table des messages.

Deuxièmement, comme Charles l'a déjà indiqué en déclarant une FOREIGN KEY sur les messages (user_id), les utilisateurs de REFERENCES (id) vous permettront de garantir l'intégrité de vos données. À l'aide d'une contrainte de clé étrangère, vous pouvez spécifier l'action à exécuter lorsqu'un enregistrement de la table des utilisateurs contenant les enregistrements correspondants dans la table des messages est supprimé. Vos choix sont ON DELETE CASCADE (supprimez tous les enregistrements enfants de cet enregistrement utilisateur), ON DELETE RESTRICT (n'autorisez pas la suppression d'un utilisateur possédant des enregistrements dans la table des messages), ON DELETE NO ACTION (ignore les opérations de suppression) , ON DELETE SET NULL (conserve les enregistrements enfants mais définit le champ user_id sur NULL).

Chacune de ces options est appropriée en fonction des circonstances, mais le plus important est de pouvoir empêcher les pointeurs null inattendus de la table enfant à la table parent.

Troisièmement, l’établissement de la relation FOREIGN KEY générera des gains de performances car il générera un INDEX sur les messages (user_id) qui correspond à PRIMARY KEY sur la table users. Lorsque vous effectuez une requête qui associe ces champs, vous constaterez que le nombre d’enregistrements devant être interrogés pour renvoyer les enregistrements enfants est considérablement réduit par rapport au fait que la clé étrangère n’a pas été établie.

@Charles Bretana - La question à laquelle vous vous connectez est spécifique à Microsoft SQL Server. La question ici concerne MySQL / InnoDB.

Je vous recommande de consulter la documentation de Contraintes de clés étrangères InnoDB .

  

InnoDB requiert des index sur les devises étrangères.   clés et clés référencées afin que   les contrôles de clé étrangère peuvent être rapides et non   besoin d'un scan de table. dans le   table de référencement, il doit y avoir un   index où les colonnes de clé étrangère   sont répertoriés comme les premières colonnes du   même ordre. Un tel index est créé   sur la table de référencement automatiquement   si ça n'existe pas. (Ceci est en   contrairement à certaines versions plus anciennes,   quels index devaient être créés   explicitement ou la création de l'étranger   les contraintes clés échoueraient.)   nom_index, s'il est indiqué, est utilisé comme   décrit précédemment.

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