Tout d'abord, la raison d'être d'une base de données relationnelle (raison d'être) est de pouvoir modéliser les relations entre entités. Les jointures sont simplement les mécanismes par lesquels nous traversons ces relations. Ils ont certainement un coût minime, mais sans jointures, il n'y a vraiment aucune raison d'avoir une base de données relationnelle.
Dans le monde académique, nous apprenons des choses comme les différentes formes normales (1ère, 2ème, 3ème, Boyce-Codd, etc.), et nous apprenons différents types de clés (primaires, étrangères, alternatives, uniques, etc.) et comment ces éléments s'emboîtent pour concevoir une base de données. Et nous apprenons les rudiments de SQL ainsi que la manipulation de la structure et des données (DDL et DML).
Dans le monde de l'entreprise, bon nombre des constructions académiques se révèlent nettement moins viables qu'on ne le pensait. Un exemple parfait est la notion de clé primaire. Sur le plan académique, c'est cet attribut (ou collection d'attributs) qui identifie de manière unique une ligne dans la table. Ainsi, dans de nombreux domaines problématiques, la clé primaire académique appropriée est un composite de 3 ou 4 attributs. Cependant, presque tout le monde dans le monde de l'entreprise moderne utilise un entier séquentiel généré automatiquement comme clé primaire d'une table. Pourquoi? Deux raisons. La première est que cela rend le modèle beaucoup plus propre lorsque vous migrez des FK partout. La deuxième, et la plus pertinente pour cette question, est que la récupération de données via des jointures est plus rapide et plus efficace sur un seul entier que sur 4 colonnes varchar (comme déjà mentionné par quelques personnes).
Explorons un peu plus en profondeur deux sous-types spécifiques de bases de données du monde réel. Le premier type est une base de données transactionnelle. C'est la base de nombreuses applications de commerce électronique ou de gestion de contenu qui pilotent des sites modernes. Avec une base de données de transaction, vous optimisez fortement vers le «débit de transaction». La plupart des applications de commerce ou de contenu doivent équilibrer les performances des requêtes (à partir de certaines tables) avec les performances d'insertion (dans d'autres tables), bien que chaque application ait ses propres problèmes commerciaux uniques à résoudre.
Le deuxième type de base de données du monde réel est une base de données de rapports. Ceux-ci sont utilisés presque exclusivement pour agréger des données commerciales et pour générer des rapports commerciaux significatifs. Ils ont généralement une forme différente de celle des bases de données de transaction où les données sont générées et ils sont hautement optimisés pour la vitesse de chargement des données en masse (ETL) et les performances des requêtes avec des ensembles de données volumineux ou complexes.
Dans chaque cas, le développeur ou l'administrateur de base de données doit soigneusement équilibrer les courbes de fonctionnalité et de performance, et il existe de nombreuses astuces d'amélioration des performances des deux côtés de l'équation. Dans Oracle, vous pouvez faire ce qu'on appelle un "plan d'explication" afin de voir spécifiquement comment une requête est analysée et exécutée. Vous cherchez à maximiser l'utilisation correcte des index par la base de données. Un non-non vraiment désagréable est de mettre une fonction dans la clause where d'une requête. Chaque fois que vous faites cela, vous garantissez qu'Oracle n'utilisera aucun index sur cette colonne particulière et vous verrez probablement une analyse de table complète ou partielle dans le plan d'explication. Ce n'est qu'un exemple spécifique de la façon dont une requête pourrait être écrite qui finit par être lente, et cela n'a rien à voir avec les jointures.
Et tandis que nous parlons d'analyses de table, elles ont évidemment un impact sur la vitesse de requête proportionnellement à la taille de la table. Une analyse complète de la table de 100 lignes n'est même pas perceptible. Exécutez cette même requête sur une table avec 100 millions de lignes, et vous devrez revenir la semaine prochaine pour le retour.
Parlons de normalisation pendant une minute. C'est un autre sujet académique largement positif qui peut être trop stressé. La plupart du temps, lorsque nous parlons de normalisation, nous entendons vraiment l'élimination des données en double en les plaçant dans sa propre table et en migrant un FK. Les gens ignorent généralement toute la question de la dépendance décrite par 2NF et 3NF. Et pourtant, dans un cas extrême, il est certainement possible d'avoir une base de données BCNF parfaite, énorme et une bête complète contre laquelle écrire du code parce qu'elle est tellement normalisée.
Alors, où équilibrons-nous? Il n'y a pas de meilleure réponse. Toutes les meilleures réponses ont tendance à être un compromis entre la facilité de maintenance de la structure, la facilité de maintenance des données et la facilité de création / maintenance de code. En général, moins il y a de duplication de données, mieux c'est.
Alors pourquoi les jointures sont-elles parfois lentes? Parfois, c'est une mauvaise conception relationnelle. Parfois, c'est une indexation inefficace. Parfois, c'est un problème de volume de données. Parfois, c'est une requête horriblement écrite.
Désolé pour une réponse aussi longue, mais je me suis senti obligé de fournir un contexte plus charnu autour de mes commentaires plutôt que de simplement déclencher une réponse à 4 points.