Les requêtes JOIN sont-elles plus rapides que plusieurs requêtes? (Vous exécutez votre requête principale, puis vous exécutez de nombreux autres SELECT en fonction des résultats de votre requête principale)
Je demande car les REJOINDRE compliquerait BEAUCOUP la conception de mon application
S'ils sont plus rapides, quelqu'un peut-il approximer de combien? Si c'est 1,5x, je m'en fiche, mais si c'est 10x, je suppose que oui.
mysql
database
join
query-optimization
Thomas Bonini
la source
la source
Réponses:
C'est beaucoup trop vague pour vous donner une réponse pertinente à votre cas spécifique. Cela dépend de beaucoup de choses. Jeff Atwood (fondateur de ce site) a en fait écrit à ce sujet . Pour la plupart, cependant, si vous avez les bons index et que vous faites correctement vos JOINs, il sera généralement plus rapide de faire 1 voyage que plusieurs.
la source
Pour les jointures internes, une seule requête a du sens, car vous n'obtenez que les lignes correspondantes. Pour les jointures à gauche, plusieurs requêtes sont bien meilleures ... regardez le benchmark suivant que j'ai fait:
Requête unique avec 5 jointures
requête: 8,074508 secondes
taille du résultat: 2268000
5 requêtes consécutives
temps de requête combiné: 0,00262 secondes
taille du résultat: 165 (6 + 50 + 7 + 12 + 90)
.
Notez que nous obtenons les mêmes résultats dans les deux cas (6 x 50 x 7 x 12 x 90 = 2268000)
les jointures à gauche utilisent exponentiellement plus de mémoire avec des données redondantes.
La limite de mémoire peut ne pas être aussi mauvaise si vous ne faites qu'une jointure de deux tables, mais généralement de trois ou plus et cela vaut la peine de requêtes différentes.
En remarque, mon serveur MySQL est juste à côté de mon serveur d'applications ... donc le temps de connexion est négligeable. Si votre temps de connexion est en secondes, il y a peut-être un avantage
Franc
la source
Cette question est ancienne, mais il manque quelques repères. J'ai comparé JOIN à ses 2 concurrents:
WHERE IN(...)
ou équivalentLe résultat est clair: sur MySQL,
JOIN
c'est beaucoup plus rapide. Les requêtes N + 1 peuvent réduire considérablement les performances d'une application:Autrement dit, sauf si vous sélectionnez un grand nombre d'enregistrements qui pointent vers un très petit nombre d'enregistrements étrangers distincts. Voici une référence pour le cas extrême:
Il est très peu probable que cela se produise dans une application typique, sauf si vous joignez une relation -to-plusieurs, auquel cas la clé étrangère se trouve sur l'autre table et que vous dupliquez les données de la table principale plusieurs fois.
À emporter:
JOIN
Voir mon article sur Medium pour plus d'informations.
la source
Je suis en fait venu à cette question à la recherche d'une réponse moi-même, et après avoir lu les réponses données, je ne peux que convenir que le meilleur moyen de comparer les performances des requêtes DB est d'obtenir des nombres réels car il y a juste trop de variables à prendre en compte MAIS, je pense aussi que comparer les chiffres entre eux ne mène à rien dans presque tous les cas. Ce que je veux dire, c'est que les nombres doivent toujours être comparés à un nombre acceptable et certainement pas comparés les uns aux autres.
Je peux comprendre que si une façon d'interroger prend par exemple 0,02 seconde et l'autre 20 secondes, c'est une énorme différence. Mais que se passe-t-il si une façon d'interroger prend 0,0000000002 secondes, et l'autre prend 0,0000002 secondes? Dans les deux cas, un chemin est 1000 fois plus rapide que l'autre, mais est-ce vraiment encore "énorme" dans le second cas?
En bout de ligne, comme je le vois personnellement: s'il fonctionne bien, optez pour la solution facile.
la source
J'ai effectué un test rapide en sélectionnant une ligne dans une table de 50 000 lignes et en la rejoignant avec une ligne dans une table de 100 000 lignes. Fondamentalement ressemblait à:
contre
La méthode de sélection à deux a pris 3,7 secondes pour 50 000 lectures alors que le JOIN a pris 2,0 secondes sur mon ordinateur lent à la maison. INNER JOIN et LEFT JOIN n'ont pas fait de différence. La récupération de plusieurs lignes (par exemple, en utilisant IN SET) a donné des résultats similaires.
la source
La vraie question est: ces enregistrements ont -ils une relation un-à-un ou une relation un-à-plusieurs ?
Réponse TLDR:
S'il s'agit d'un à un, utilisez une
JOIN
instruction.S'il s'agit d'un à plusieurs, utilisez une (ou plusieurs)
SELECT
instructions avec l'optimisation du code côté serveur.Pourquoi et comment utiliser SELECT pour l'optimisation
SELECT
'ing (avec plusieurs requêtes au lieu de jointures) sur un grand groupe d'enregistrements basé sur une relation un-à-plusieurs produit une efficacité optimale, carJOIN
' ing a un problème de fuite de mémoire exponentielle. Saisissez toutes les données, puis utilisez un langage de script côté serveur pour les trier:Résultats:
Ici, je reçois tous les enregistrements, dans une seule instruction select. C'est mieux que
JOIN
, qui obtiendrait un petit groupe de ces enregistrements, un à la fois, en tant que sous-composant d'une autre requête. Ensuite, je l'analyse avec un code côté serveur qui ressemble à quelque chose comme ...Quand ne pas utiliser JOIN pour l'optimisation
JOIN
Un grand groupe d'enregistrements basé sur une relation biunivoque avec un seul enregistrement produit une efficacité optimale par rapport à plusieursSELECT
instructions, l'une après l'autre, qui obtiennent simplement le type d'enregistrement suivant.Mais
JOIN
est inefficace lors de l'obtention d'enregistrements avec une relation un-à-plusieurs.Exemple: La base de données Blogs a 3 tables d'intérêt, Blogpost, Tag et Comment.
S'il y a 1 article de blog, 2 balises et 2 commentaires, vous obtiendrez des résultats comme:
Remarquez comment chaque enregistrement est dupliqué. Bon, donc, 2 commentaires et 2 balises font 4 lignes. Et si nous avons 4 commentaires et 4 balises? Vous n'obtenez pas 8 lignes - vous obtenez 16 lignes:
Ajoutez plus de tables, plus d'enregistrements, etc., et le problème augmentera rapidement à des centaines de lignes qui sont toutes pleines de données pour la plupart redondantes.
Combien vous coûtent ces doublons? Mémoire (dans le serveur SQL et le code qui tente de supprimer les doublons) et ressources réseau (entre le serveur SQL et votre serveur de code).
Source: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html
la source
Construisez à la fois des requêtes et des jointures séparées, puis chronométrez chacune d'elles - rien ne sert plus que des nombres réels.
Alors encore mieux - ajoutez "EXPLAIN" au début de chaque requête. Cela vous indiquera combien de sous-requêtes MySQL utilise pour répondre à votre demande de données, et combien de lignes analysées pour chaque requête.
la source
En fonction de la complexité de la base de données par rapport à la complexité du développeur, il peut être plus simple d'effectuer de nombreux appels SELECT.
Essayez d'exécuter des statistiques de base de données sur le JOIN et les multiples SELECTS. Voyez si dans votre environnement le JOIN est plus rapide / plus lent que le SELECT.
Là encore, si le changer en JOIN signifierait un jour / semaine / mois supplémentaire de travail de développement, je m'en tiendrai à plusieurs SELECT
À votre santé,
BLT
la source
D'après mon expérience, j'ai trouvé qu'il est généralement plus rapide d'exécuter plusieurs requêtes, en particulier lors de la récupération de grands ensembles de données.
Lors de l'interaction avec la base de données à partir d'une autre application, telle que PHP, il y a l'argument d'un voyage vers le serveur sur plusieurs.
Il existe d'autres moyens de limiter le nombre de trajets effectués sur le serveur et d'exécuter encore plusieurs requêtes qui sont souvent non seulement plus rapides, mais facilitent également la lecture de l'application - par exemple mysqli_multi_query.
Je ne suis pas novice en matière de SQL, je pense que les développeurs, en particulier les juniors, ont tendance à passer beaucoup de temps à essayer d'écrire des jointures très intelligentes parce qu'elles ont l'air intelligentes, alors qu'il existe en fait des moyens intelligents d'extraire des données qui semblent Facile.
Le dernier paragraphe était une opinion personnelle, mais j'espère que cela aide. Je suis cependant d'accord avec les autres qui disent que vous devriez évaluer. Aucune des deux approches n'est une solution miracle.
la source
Si vous utilisez une jointure est d' abord et avant tout de savoir si une jointure est logique . Ce n'est qu'à ce stade que les performances doivent être prises en compte, car presque tous les autres cas entraîneront des performances nettement moins bonnes.
Les différences de performances seront en grande partie liées à la relation entre les informations que vous recherchez. Les jointures fonctionnent et elles sont rapides lorsque les données sont liées et que vous indexez correctement les éléments, mais elles entraînent souvent une certaine redondance et parfois plus de résultats que nécessaire. Et si vos ensembles de données ne sont pas directement liés, les coller dans une seule requête aboutira à ce qu'on appelle un produit cartésien (en gros, toutes les combinaisons possibles de lignes), ce qui n'est presque jamais ce que vous voulez.
Ceci est souvent causé par des relations plusieurs-à-un-à-plusieurs. Par exemple, la réponse de HoldOffHunger mentionnait une seule requête pour les publications, les tags et les commentaires. Les commentaires sont liés à un article, tout comme les balises ... mais les balises ne sont pas liées aux commentaires.
Dans ce cas, il est clairement préférable que ce soit au moins deux requêtes distinctes. Si vous essayez de joindre des balises et des commentaires, car il n'y a pas de relation directe entre les deux, vous vous retrouvez avec toutes les combinaisons possibles de balise et de commentaire.
many * many == manymany
. En dehors de cela, comme les publications et les tags ne sont pas liés, vous pouvez effectuer ces deux requêtes en parallèle, ce qui entraîne un gain potentiel.Considérons un scénario différent, cependant: vous voulez que les commentaires soient joints à un article et les coordonnées des commentateurs.
C'est là que vous devriez envisager une jointure. En plus d'être une requête beaucoup plus naturelle, la plupart des systèmes de base de données (y compris MySQL) ont beaucoup de gens intelligents qui travaillent dur pour optimiser les requêtes comme ça. Pour les requêtes séparées, puisque chaque requête dépend des résultats de la précédente, les requêtes ne peuvent pas être effectuées en parallèle et le temps total devient non seulement le temps réel d'exécution des requêtes, mais également le temps passé à récupérer les résultats, à passer au crible à travers eux pour les identifiants de la requête suivante, reliant les lignes entre elles, etc.
la source
Sera-ce plus rapide en termes de débit? Probablement. Mais il verrouille également potentiellement plus d'objets de base de données à la fois (en fonction de votre base de données et de votre schéma) et diminue ainsi la concurrence. D'après mon expérience, les gens sont souvent induits en erreur par l'argument "moins d'aller-retour de base de données" alors qu'en réalité sur la plupart des systèmes OLTP où la base de données est sur le même LAN, le véritable goulot d'étranglement est rarement le réseau.
la source
Voici un lien avec 100 requêtes utiles, celles-ci sont testées dans la base de données Oracle mais rappelez-vous que SQL est une norme, ce qui diffère entre Oracle, MS SQL Server, MySQL et d'autres bases de données est le dialecte SQL:
http://javaforlearn.com/100-sql-queries-learn/
la source
Il y a plusieurs facteurs qui signifient qu'il n'y a pas de réponse binaire. La question de savoir ce qui est le mieux pour les performances dépend de votre environnement. À propos, si votre sélection unique avec un identifiant n'est pas inférieure à la seconde, il se peut que quelque chose ne tourne pas rond avec votre configuration.
La vraie question à se poser est de savoir comment voulez-vous accéder aux données. Les sélections uniques prennent en charge la liaison tardive. Par exemple, si vous souhaitez uniquement des informations sur les employés, vous pouvez effectuer une sélection dans la table Employés. Les relations de clé étrangère peuvent être utilisées pour récupérer les ressources associées ultérieurement et selon les besoins. Les sélections auront déjà une clé sur laquelle pointer, elles devraient donc être extrêmement rapides et vous n'avez qu'à récupérer ce dont vous avez besoin. La latence du réseau doit toujours être prise en compte.
Les jointures récupéreront toutes les données à la fois. Si vous générez un rapport ou remplissez une grille, c'est peut-être exactement ce que vous voulez. Les jointures compilées et optimisées seront tout simplement plus rapides que les sélections uniques dans ce scénario. N'oubliez pas que les jointures ad hoc peuvent ne pas être aussi rapides - vous devez les compiler (dans un processus stocké). La réponse rapide dépend du plan d'exécution, qui détaille exactement les étapes suivies par le SGBD pour récupérer les données.
la source
Oui, une requête utilisant JOINS serait plus rapide. Bien que sans connaître les relations des tables que vous interrogez, la taille de votre ensemble de données ou l'emplacement des clés primaires, il est presque impossible de dire combien plus rapidement.
Pourquoi ne pas tester les deux scénarios, alors vous saurez avec certitude ...
la source