La clé étrangère améliore-t-elle les performances des requêtes?

149

Supposons que j'ai 2 tables, produits et catégories de produits. Les deux tables ont une relation sur CategoryId. Et c'est la question.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

Lorsque je crée un plan d'exécution, la table ProductCategories effectue une recherche d'index de cluster, ce qui est attendu. Mais pour les produits de table, il effectue une analyse d'index de cluster, ce qui me fait douter. Pourquoi FK n'aide pas à améliorer les performances des requêtes?

Je dois donc créer un index sur Products.CategoryId. Lorsque je crée à nouveau le plan d'exécution, les deux tables effectuent une recherche d'index. Et le coût estimé du sous-arbre est considérablement réduit.

Mes questions sont:

  1. A côté de FK aide sur la contrainte relationnelle, a-t-il une autre utilité? Améliore-t-il les performances des requêtes?

  2. Dois-je créer un index sur toutes les colonnes FK (comme Products.CategoryId) dans toutes les tables?

Chaowlert Chaisrichalermpol
la source

Réponses:

186

Les clés étrangères sont un outil d'intégrité référentielle, pas un outil de performance. Au moins dans SQL Server, la création d'un FK ne crée pas d'index associé et vous devez créer des index sur tous les champs FK pour améliorer les temps de recherche.

cmsjr
la source
40
Les bons modèles fonctionnent (généralement) mieux.
Kenny Evitt
10
«Les clés étrangères sont un outil d'intégrité relationnelle» - veuillez utiliser le mot «relationnel» avec précaution. Les clés étrangères sont un concept de base de données, un raccourci pour une contrainte d'intégrité référentielle. Ils ne font pas partie du modèle relationnel. Je suppose que vous avez fait une faute de frappe.
jour du
7
@Kenny Souvent oui, mais parfois un meilleur modèle coûte plus cher. Exemple concret: les clés étrangères entraînent plus de traitement, pas moins.
Hans
8
clés étrangères font améliorer les performances, au moins dans MySQL. De plus, vous avez raison, la création d'un FK ne crée pas d'index; la création d'un FK nécessite un index
Félix Gagnon-Grenier
15
Cette réponse est pratiquement inutile car elle ne répond pas à la question. Il est bon de savoir que les clés étrangères ne sont pas destinées à avoir un effet (positif) sur les performances, mais la question concernait la réalité, pas les intentions.
John
58

Les clés étrangères peuvent améliorer (et nuire) les performances

  1. Comme indiqué ici: les clés étrangères améliorent les performances

  2. Vous devez toujours créer des index sur les colonnes FK pour réduire les recherches. SQL Server ne le fait pas automatiquement.

Éditer

Comme le lien semble maintenant mort (bravo à Chris pour l'avoir remarqué) , ce qui suit montre l'essentiel des raisons pour lesquelles les clés étrangères peuvent améliorer (et nuire) les performances.

La clé étrangère peut-elle améliorer les performances

La contrainte de clé étrangère améliore les performances au moment de la lecture des données, mais en même temps elle ralentit les performances au moment de l'insertion / de la modification / de la suppression des données.

En cas de lecture de la requête, l'optimiseur peut utiliser des contraintes de clé étrangère pour créer des plans de requête plus efficaces car les contraintes de clé étrangère sont des règles pré-déclarées. Cela implique généralement de sauter une partie du plan de requête car, par exemple, l'optimiseur peut voir qu'en raison d'une contrainte de clé étrangère, il n'est pas nécessaire d'exécuter cette partie particulière du plan.

Lieven Keersmaekers
la source
3
Voici un lien qui détaille les moyens par lesquels ils peuvent dégrader les performances devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr
3
Cela a du sens, mais vous ne rencontrerez cela qu'avec une instruction de suppression massive. La conclusion devrait peut-être être que dans les environnements OLAP, les FK non indexés amélioreraient les performances tandis que dans les environnements OLTP, cela dégraderait les performances.
Lieven Keersmaekers le
1
Le lien dans cette réponse est mort. C'est dommage car c'est le seul argument ici pour que les FK améliorent les performances.
Chris Moschini
1
@ChrisMoschini - Je n'ai pas remarqué votre commentaire jusqu'à présent. Comme vous l'avez mentionné, le lien est mort mais l'essentiel est mentionné dans le nouveau lien (avec des détails) que j'ai publié.
Lieven Keersmaekers
2
Lien Wayback Machine pour la victoire! L'article peut également être trouvé sur SQLMag.com, ici .
John Eisbrener
15

Une clé étrangère est un concept de SGBD pour garantir l'intégrité de la base de données.

Toutes les implications / améliorations de performances seront spécifiques à la technologie de base de données utilisée et sont secondaires par rapport à l'objectif d'une clé étrangère.

Il est recommandé dans SQL Server de s'assurer que toutes les clés étrangères ont au moins un index non clusterisé sur elles.

J'espère que cela clarifie les choses pour vous, mais n'hésitez pas à demander plus de détails.

John Sansom
la source
9
@Kenny Evitt si vous n'avez pas d'intégrité, vos données sont inutiles. Je trouve que ça se vend très facilement.
HLGEM
@HLGEM Obtenir une erreur 404 de temps en temps est encore assez supportable. Avoir en retour un débit exceptionnel en utilisant des ressources moins chères et des systèmes moins complexes, maintenant cela se vend très facilement aussi. Vous pourriez être intéressé par le théorème CAP .
Daniel Dinnyes
8
@Daniel Dinnyes, l'intégrité des données ne consiste pas à obtenir une erreur 404. Il s'agit d'avoir des données utilisables. Il s'agit de ne pas perdre de commandes et de données financières pour les rapports par exemple à cause de l'incompétence des développeurs. Il n'y a AUCUNE EXCUSE pour ne pas utiliser de clés étrangères.
HLGEM
2
Je suis d'accord avec HLGEM. Laisser votre code gérer l'intégrité n'est pas toujours une bonne idée. Les données sont souvent utilisées pour prendre des décisions, mais si les données sont corrompues, la décision ne sera pas exacte.
lepe
1
«Les clés étrangères sont un outil d'intégrité relationnelle» - veuillez utiliser le mot «relationnel» avec précaution. Les clés étrangères sont un concept de base de données, un raccourci pour une contrainte d'intégrité référentielle. Ils ne font pas partie du modèle relationnel. Je suppose que vous avez fait une faute de frappe.
jour du
4

Votre meilleur pari de performance est d'utiliser des index sur les champs que vous utilisez fréquemment. Si vous utilisez SQL Server, vous pouvez utiliser le profileur pour profiler une base de données spécifique et prendre le fichier qui génère et utiliser l'assistant de réglage pour recevoir des recommandations sur l'emplacement de vos index. J'aime aussi utiliser le profiler pour éliminer les procédures stockées de longue durée, j'ai une liste des dix pires contrevenants que je publie chaque semaine, pour que les gens restent honnêtes: D.

Al Katawazi
la source
3

Vous pouvez l'utiliser pour rendre une requête plus efficace. Il vous permet de restructurer les requêtes dans SQL Server pour utiliser une jointure externe au lieu d'une jointure interne, ce qui supprime la nécessité pour les serveurs SQL de vérifier s'il y a une valeur nulle dans la colonne. Vous n'avez pas besoin de mettre ce qualificatif car la relation de clé étrangère l'informe déjà pour vous.

Donc ça:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Devient ceci:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

Cela n'entraînera pas nécessairement d'énormes performances dans les petites requêtes, mais lorsque les tables deviennent volumineuses, cela peut être plus efficace.

kemiller2002
la source
3
Non seulement les jointures externes sont généralement moins efficaces que les jointures internes ( stackoverflow.com/a/2726683/155892 ), mais maintenant vos requêtes sont trompeuses: vous comptez sur la base de données pour transformer implicitement vos jointures externes en jointures internes (restauration des performances) au lieu de simplement le faire explicitement
Mark Sowul
2

Pour MySQL 5.7, il peut certainement accélérer les requêtes impliquant plusieurs jointures incroyablement bien!

J'ai utilisé «expliquer» pour comprendre ma requête et j'ai trouvé que je rejoignais 4 à 5 tables - où aucune clé n'était utilisée du tout. Je n'ai rien fait d'autre que d'ajouter une clé étrangère à ces tables et le résultat a été une réduction de 90% du temps de chargement. Les requêtes qui prenaient plus de 5 secondes prennent désormais 500 ms ou moins.

C'est une amélioration ÉNORME!

ET, comme d'autres l'ont mentionné, vous obtenez l'avantage supplémentaire d'assurer l'intégrité relationnelle.

Au-delà de cela, garantir l'intégrité référentielle a également ses propres avantages en termes de performances. Il a pour effet de second ordre de garantir que les tables qui ont la clé étrangère sont «à jour» avec la table étrangère. Supposons que vous ayez une table des utilisateurs et une table des commentaires, et que vous fassiez des statistiques sur la table des commentaires. Probablement si vous supprimez définitivement l'utilisateur, vous ne voulez plus ses commentaires non plus.

Peter Bartlett
la source
Les tables disposaient-elles des index requis pour générer les clés étrangères avant de les ajouter?
George
1

L'ajout d'une clé étrangère dans la table n'améliorera pas les performances, il suffit de dire que si vous insérez un enregistrement dans une base de données de table ProductCategories essaiera de trouver que la colonne de clé étrangère a une valeur qui existe dans la valeur de clé primaire d'une table products, cette recherche, l'opération est une surcharge sur votre base de données chaque fois que vous ajoutez une nouvelle entrée dans la table ProductCategories. Ainsi, l'ajout d'une clé étrangère n'améliorera pas les performances de votre base de données mais prendra soin de l'intégrité de votre base de données. Oui, cela améliorera les performances de votre base de données si vous vérifiez l'intégrité à l'aide d'une clé étrangère au lieu d'exécuter de nombreuses requêtes pour vérifier que l'enregistrement existe dans la base de données de votre programme.

Pankaj Khairnar
la source
0

Je ne sais pas grand-chose sur le serveur SQL, mais dans le cas d'Oracle, avoir une colonne de clé étrangère réduit les performances de chargement des données. En effet, la base de données doit vérifier l'intégrité des données pour chaque insertion. Et oui, comme il est déjà mentionné, avoir un index sur la colonne de clé étrangère est une bonne pratique.

Shamik
la source