L'évolutivité consiste à pré-calculer, à répartir ou à réduire le travail répété à l'essentiel, afin de minimiser l'utilisation des ressources par unité de travail. Pour bien évoluer, vous ne faites rien dont vous n'avez pas besoin en volume, et vous vous assurez que les choses que vous faites sont faites aussi efficacement que possible.
Dans ce contexte, bien sûr, joindre deux sources de données distinctes est relativement lent, du moins par rapport au fait de ne pas les joindre, car c'est un travail que vous devez faire en direct au moment où l'utilisateur le demande.
Mais rappelez-vous que l'alternative est de ne plus avoir du tout deux éléments de données séparés; vous devez mettre les deux points de données disparates dans le même enregistrement. Vous ne pouvez pas combiner deux données différentes sans conséquence quelque part, alors assurez-vous de bien comprendre le compromis.
La bonne nouvelle est que les bases de données relationnelles modernes sont bonnes pour les jointures. Vous ne devriez pas vraiment penser aux jointures comme lentes avec une bonne base de données bien utilisée. Il existe un certain nombre de moyens d'évolutivité pour prendre des jointures brutes et les rendre beaucoup plus rapides:
- Rejoignez sur une clé de substitution (autonumer / colonne d'identité) plutôt que sur une clé naturelle. Cela signifie des comparaisons plus petites (et donc plus rapides) pendant l'opération de jointure
- Index
- Vues matérialisées / indexées (considérez cela comme une jointure pré-calculée ou une dénormalisation gérée )
- Colonnes calculées. Vous pouvez l'utiliser pour hacher ou pré-calculer les colonnes clés d'une jointure, de sorte que ce qui serait une comparaison compliquée pour une jointure est maintenant beaucoup plus petit et potentiellement pré-indexé.
- Partitions de table (aide avec de grands ensembles de données en répartissant la charge sur plusieurs disques, ou en limitant ce qui aurait pu être une analyse de table à une analyse de partition)
- OLAP (pré-calcule les résultats de certains types de requêtes / jointures. Ce n'est pas tout à fait vrai, mais vous pouvez considérer cela comme une dénormalisation générique )
- Réplication, groupes de disponibilité, envoi de journaux ou autres mécanismes permettant à plusieurs serveurs de répondre aux requêtes de lecture pour la même base de données, et ainsi de redimensionner votre charge de travail entre plusieurs serveurs.
- Utilisation d'une couche de mise en cache comme Redis pour éviter de réexécuter des requêtes nécessitant des jointures complexes.
J'irais jusqu'à dire que la principale raison pour laquelle les bases de données relationnelles existent est de vous permettre de faire des jointures efficacement * . Ce n'est certainement pas seulement pour stocker des données structurées (vous pouvez le faire avec des constructions de fichier plat comme csv ou xml). Certaines des options que j'ai énumérées vous permettront même de créer complètement votre jointure à l'avance, de sorte que les résultats sont déjà faits avant d'émettre la requête - tout comme si vous aviez dénormalisé les données (certes au prix d'opérations d'écriture plus lentes).
Si vous avez une jointure lente, vous n'utilisez probablement pas correctement votre base de données.
La dénormalisation ne doit être effectuée qu'après l'échec de ces autres techniques. Et la seule façon de vraiment juger de «l'échec» est de fixer des objectifs de performance significatifs et de les mesurer par rapport à ces objectifs. Si vous n'avez pas mesuré, il est trop tôt pour même penser à la dénormalisation.
* Autrement dit, existent en tant qu'entités distinctes de simples collections de tables. Une raison supplémentaire pour un vrai rdbms est l'accès simultané sécurisé.
Les jointures peuvent être plus lentes que de les éviter par la dénormalisation, mais si elles sont utilisées correctement (jointure sur des colonnes avec des index appropriés, etc.), elles ne sont pas intrinsèquement lentes .
La dé-normalisation est l'une des nombreuses techniques d'optimisation que vous pouvez envisager si votre schéma de base de données bien conçu présente des problèmes de performances.
la source
l'article dit qu'ils sont lents par rapport à l'absence de jointures. ceci peut être réalisé avec la dénormalisation. il y a donc un compromis entre vitesse et normalisation. n'oubliez pas l'optimisation prématurée également :)
la source
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.
la source
Les personnes ayant des bases de données de taille terrabyte utilisent toujours des jointures, si elles peuvent les faire fonctionner en termes de performances, vous le pouvez également.
Il y a de nombreuses raisons de ne pas dénomaliser. Premièrement, la vitesse des requêtes de sélection n'est pas la seule ni même la principale préoccupation des bases de données. L'intégrité des données est la première préoccupation. Si vous dénormalisez, vous devez mettre en place des techniques pour conserver les données dénormalisées à mesure que les données parentes changent. Supposons donc que vous preniez pour stocker le nom du client dans toutes les tables au lieu de rejoindre la table client sur le client_Id. Désormais, lorsque le nom du client change (100% de chances que certains des noms de clients changent au fil du temps), vous devez maintenant mettre à jour tous les enregistrements enfants pour refléter ce changement. Si vous faites cela avec une mise à jour en cascade et que vous avez un million d'enregistrements enfants, à quelle vitesse pensez-vous que cela va être et combien d'utilisateurs vont souffrir de problèmes de verrouillage et de retards dans leur travail pendant que cela se produit? En outre, la plupart des gens qui dénormalisent parce que "
La dénormalisation est un processus complexe qui nécessite une compréhension approfondie des performances et de l'intégrité de la base de données pour être effectuée correctement. N'essayez pas de dénormaliser à moins d'avoir une telle expertise au sein du personnel.
Les jointures sont assez rapides si vous faites plusieurs choses. Utilisez d'abord une clé suggérée, une jointure int est presque toujours la jointure la plus rapide. Deuxièmement, indexez toujours la clé étrangère. Utilisez des tables dérivées ou des conditions de jointure pour créer un ensemble de données plus petit sur lequel filtrer. Si vous avez une grande base de données très complexe, engagez un spécialiste des bases de données expérimenté dans le partage et la gestion d'énormes bases de données. Il existe de nombreuses techniques pour améliorer les performances sans se débarrasser des jointures.
Si vous avez juste besoin d'une capacité de requête, alors oui, vous pouvez concevoir un entrepôt de données qui peut être dénormalisé et alimenté via un outil ETL (optimisé pour la vitesse) et non la saisie de données utilisateur.
la source
Les jointures sont lentes si
Donc, vrai, plus vos ensembles de données sont volumineux, plus vous aurez besoin de traitement pour une requête, mais vérifier et travailler sur les trois premières options de ce qui précède donnera souvent d'excellents résultats.
Votre source propose la dénormalisation en option. Cela ne fonctionne que tant que vous avez épuisé les meilleures alternatives.
la source
Les jointures peuvent être lentes si de grandes parties d'enregistrements de chaque côté doivent être analysées.
Comme ça:
Même si un index est défini sur
account_customer
, tous les enregistrements de ce dernier doivent encore être analysés.Pour la liste de requêtes, les optimiseurs décents ne prendront probablement même pas en compte le chemin d'accès à l'index, en faisant un
HASH JOIN
ou un à laMERGE JOIN
place.Notez que pour une requête comme celle-ci:
la jointure sera très probablement rapide: d'abord, un index sur
customer_last_name
sera utilisé pour filtrer tous les Stellphlug (qui sont bien sûr peu nombreux), puis un scan d'index suraccount_customer
sera émis pour chaque Stellphlug pour trouver ses transactions.Malgré le fait qu'il peut s'agir de milliards d'enregistrements dans
accounts
etcustomers
, seuls quelques-uns devront réellement être numérisés.la source
accounts(account_customer)
plupart des SGBDR, il utilisera cet index pour savoir exactement quelles lignes de lacustomers
base de données doivent être analysées.HASH JOIN
serait beaucoup plus rapide, c'est donc ce qui sera utilisé sauf dans toutes les principales bases de données saufMySQL
, qui ne fera quecustomers
mener une boucle imbriquée (car sa taille est plus petite)Joins are fast.
Les jointures doivent être considérées comme une pratique standard avec un schéma de base de données correctement normalisé. Les jointures vous permettent de rejoindre des groupes de données disparates de manière significative. N'ayez pas peur de la jointure.La mise en garde est que vous devez comprendre la normalisation, la jonction et l'utilisation correcte des index.
Méfiez-vous de l'optimisation prématurée, car le principal échec de tous les projets de développement est de respecter les délais. Une fois que vous avez terminé le projet et que vous comprenez les compromis, vous pouvez enfreindre les règles si vous pouvez le justifier.
Il est vrai que les performances de jointure se dégradent de manière non linéaire à mesure que la taille de l'ensemble de données augmente. Par conséquent, il ne s'adapte pas aussi bien que les requêtes de table unique, mais il évolue toujours.
Il est également vrai qu'un oiseau vole plus vite sans ailes, mais seulement tout droit.
la source
Les jointures nécessitent un traitement supplémentaire car elles doivent rechercher plus de fichiers et plus d'index pour «joindre» les données ensemble. Cependant, les «très grands ensembles de données» sont tous relatifs. Qu'elle est la définition de grand? Dans le cas des JOINs, je pense que c'est une référence à un grand ensemble de résultats, pas à cet ensemble de données global.
La plupart des bases de données peuvent traiter très rapidement une requête qui sélectionne 5 enregistrements dans une table principale et joint 5 enregistrements à partir d'une table associée pour chaque enregistrement (en supposant que les index corrects sont en place). Ces tables peuvent contenir des centaines de millions d'enregistrements chacune, voire des milliards.
Une fois que votre jeu de résultats commence à grandir, les choses vont ralentir. En utilisant le même exemple, si la table principale aboutit à 100 000 enregistrements, alors il y aura 500 000 enregistrements «joints» à trouver. Il suffit d'extraire autant de données de la base de données avec des retards supplémentaires.
N'évitez pas les JOIN, sachez simplement que vous devrez peut-être optimiser / dénormaliser lorsque les ensembles de données deviennent "très volumineux".
la source
Également extrait de l'article que vous avez cité:
et
et
L'article traite de méga-sites comme Ebay. À ce niveau d'utilisation, vous devrez probablement envisager autre chose que la gestion de base de données relationnelle simple. Mais dans le cours «normal» des affaires (applications avec des milliers d'utilisateurs et des millions d'enregistrements), les approches les plus coûteuses et les plus sujettes aux erreurs sont exagérées.
la source
Les jointures sont considérées comme une force opposée à l'évolutivité, car elles constituent généralement le goulot d'étranglement et ne peuvent pas être facilement distribuées ou mises en parallèle.
la source
Des tableaux correctement conçus contenant les indices appropriés et des requêtes correctement écrites ne sont pas toujours lents. Où que vous ayez entendu ça:
n'a aucune idée de ce dont ils parlent !!! La plupart des jointures seront très rapides. Si vous devez joindre plusieurs lignes à la fois, vous risquez de prendre un coup par rapport à une table dénormalisée, mais cela revient à Tables correctement conçues, sachez quand dénormaliser et quand ne pas le faire. dans un système de reporting lourd, divisez les données dans des tableaux dénormalisés pour les rapports, ou même créez un entrepôt de données. Dans un système transactionnel lourd, normalisez les tables.
la source
La quantité de données temporaires générées peut être énorme en fonction des jointures.
Par exemple, une base de données ici au travail avait une fonction de recherche générique où tous les champs étaient facultatifs. La routine de recherche a effectué une jointure sur chaque table avant le début de la recherche. Cela a bien fonctionné au début. Mais, maintenant que la table principale a plus de 10 millions de lignes ... pas tellement. Les recherches prennent maintenant 30 minutes ou plus.
J'ai été chargé d'optimiser la procédure de recherche stockée.
La première chose que j'ai faite a été si l'un des champs de la table principale était recherché, j'ai fait une sélection dans une table temporaire sur ces champs uniquement. ALORS, j'ai joint toutes les tables avec cette table temporaire avant de faire le reste de la recherche. Les recherches dans lesquelles l'un des champs de la table principale prennent désormais moins de 10 secondes.
Si aucun des champs de la table principale n'est recherché, je fais des optimisations similaires pour d'autres tables. Lorsque j'ai terminé, aucune recherche ne prend plus de 30 secondes avec la plupart sous 10.
L'utilisation du processeur du serveur SQL a également diminué.
la source
Alors que les jointures (probablement dues à une conception normalisée) peuvent évidemment être plus lentes pour la récupération de données qu'une lecture à partir d'une seule table, une base de données dénormalisée peut être lente pour les opérations de création / mise à jour de données puisque l'empreinte de la transaction globale ne sera pas minimale.
Dans une base de données normalisée, une donnée ne vivra qu'à un seul endroit, de sorte que l'empreinte d'une mise à jour sera aussi minime que possible. Dans une base de données dénormalisée, il est possible que la même colonne dans plusieurs lignes ou entre les tables doive être mise à jour, ce qui signifie que l'empreinte serait plus grande et que le risque de verrous et de blocages peut augmenter.
la source
Eh bien, oui, la sélection de lignes dans une table dénormalisée (en supposant des index décents pour votre requête) peut être plus rapide que la sélection de lignes construites à partir de la jointure de plusieurs tables, en particulier si les jointures ne disposent pas d'index efficaces.
Les exemples cités dans l'article - Flickr et eBay - sont des cas exceptionnels de l'OMI, donc ont (et méritent) des réponses exceptionnelles. L'auteur évoque spécifiquement le manque de RI et l'étendue de la duplication des données dans l'article.
La plupart des applications - encore une fois, IMO - bénéficient de la validation et de la réduction des doublons fournis par les SGBDR.
la source
Ils peuvent être lents s'ils sont faits avec négligence. Par exemple, si vous faites un 'select *' sur une jointure, vous prendrez probablement un certain temps pour récupérer les choses. Cependant, si vous choisissez soigneusement les colonnes à renvoyer à partir de chaque table et avec les index appropriés en place, il ne devrait y avoir aucun problème.
la source