Supposons que j'ai 2 tables, Products et ProductCategories. Les deux tables ont une relation sur CategoryId. Et c'est la requête.
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, qui correspond aux attentes. Mais pour les produits de table, il effectue une analyse d'index de cluster, ce qui me fait douter. Pourquoi FK n'aide-t-il pas à améliorer les performances des requêtes?
Je dois donc créer un index sur Products.CategoryId. Lorsque je crée à nouveau un plan d'exécution, les deux tables effectuent une recherche d'index. Et le coût estimé des sous-arbres est considérablement réduit.
Mes questions sont:
En plus d'aider FK sur la contrainte de relation, est-ce qu'elle a une autre utilité? Améliore-t-il les performances des requêtes?
Devrais-je créer un index sur toutes les colonnes FK (J'aime Products.CategoryId) dans toutes les tables?
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.
Les clés étrangères peuvent améliorer (et nuire) aux performances
Comme indiqué ici: Les clés étrangères améliorent les performances
Vous devez toujours créer des index sur les colonnes FK pour réduire les recherches. SQL Server ne le fait pas automatiquement.
Modifier
Comme le lien semble maintenant être mort (félicitations à Chris pour l'avoir remarqué)}, ce qui suit montre de manière générale pourquoi 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 données, mais en même temps, cela ralentit les performances au moment de insertion/modification/suppression de 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 en tant que clé étrangère les contraintes sont des règles pré-déclarées. Cela implique généralement de sauter une partie du plan de requête parce que, 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 du plan.
Une clé étrangère est un concept de SGBD destiné à assurer l'intégrité de la base de données.
Toute implication/amélioration des performances sera spécifique à la technologie de base de données utilisée et est secondaire à l'objectif d'une clé étrangère.
Il est de bonne pratique dans SQL Server de s’assurer que toutes les clés étrangères ont au moins un index non clusterisé.
J'espère que cela clarifie les choses pour vous, mais n'hésitez pas à demander plus de détails.
Votre meilleure 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, récupérer le fichier qui est généré et utiliser l'assistant de réglage pour recevoir des recommandations sur l'emplacement de vos index. J'aime aussi utiliser Profiler pour effacer les procédures stockées de longue durée. J'ai la liste des dix pires délinquants que je publie chaque semaine, je tiens les gens honnêtes: D.
Vous pouvez l'utiliser pour rendre une requête plus efficace. Cela vous permet de restructurer des requêtes dans SQL Server pour utiliser une jointure externe au lieu d'une jointure interne qui supprime la nécessité pour les serveurs SQL de vérifier s'il existe une valeur null dans la colonne. Vous n’avez pas besoin de mettre ce qualificatif, car la relation de clé étrangère l’infirme 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 ne fera pas forcément une performance énorme dans les petites requêtes, mais lorsque les tables deviennent grandes, cela peut être plus efficace.
Je ne connais pas beaucoup le serveur SQL, mais dans le cas d'Oracle, le fait de disposer d'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 a déjà été mentionné, disposer d’un index sur une colonne de clé étrangère est une bonne pratique.
L'ajout d'une clé étrangère dans la table n'améliorera pas les performances. Si vous insérez un enregistrement dans une base de données de table ProductCategories, la colonne de clé étrangère a une valeur qui existe dans la valeur de clé primaire d'une table de produits. Chaque fois que vous ajoutez une nouvelle entrée dans la table ProductCategories, l'opération entraîne une surcharge de votre base de données. Ainsi, l'ajout d'une clé étrangère n'améliorera pas les performances de votre base de données, mais il veillera à l'intégrité de votre base de données. améliorer les performances de votre base de données si vous vérifiez l'intégrité en utilisant 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.
Pour MySQL 5.7, cela accélère énormément les requêtes impliquant plusieurs jointures!
J'ai utilisé 'expliquer' pour comprendre ma requête et j'ai découvert que je rejoignais 4 ou 5 tables, où aucune clé n'était utilisée. 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 ont pris> 5 secondes prennent maintenant 500 ms ou moins.
C'est une amélioration ENORME!
ET, comme d’autres l’ont mentionné, vous bénéficiez de l’assurance intégrité relationnelle.
Au-delà de cela, assurer l’intégrité référentielle a également ses avantages en termes de performances. Cela a pour effet de second ordre de s'assurer que les tables qui ont la clé étrangère sont «à jour» avec la table étrangère. Supposons que vous ayez une table d'utilisateurs et une table de commentaires et que vous établissiez des statistiques sur la table de commentaires. Probablement si vous supprimez durement l'utilisateur, vous ne voulez plus non plus leurs commentaires.
A partir de SQL Server 2008, les clés étrangères peuvent influer sur les performances en influant sur la façon dont le moteur de base de données choisit d'optimiser la requête. Reportez-vous aux heuristiques de jointure d'étoiles dans l'article suivant: https://technet.Microsoft.com/en-us/library/2008.04.dwperformance.aspx