Question

sont REJOIGNEZ requêtes plus rapidement que plusieurs requêtes? (Vous exécutez votre requête principale, puis vous exécutez beaucoup d'autres SELECTs sur la base des résultats de votre requête principale)

Je demande parce que cela compliquerait les joindre à BEAUCOUP la conception de ma demande

Si elles sont plus rapides, peut-on rapprocher très à peu près combien? Si c'est 1.5x Je ne me soucie pas, mais si elle est 10 fois je crois que je fais.

Était-ce utile?

La solution

est trop vague pour vous donner une réponse pertinente à votre cas particulier. Cela dépend de beaucoup de choses. Jeff Atwood (fondateur de ce site) fait a écrit sur cette . Pour la plupart, cependant, si vous avez les index à droite et vous faites correctement votre JOIN il va généralement être plus rapide à faire 1 voyage que plusieurs.

Autres conseils

Pour les jointures internes, une seule requête est logique, puisque vous obtenez seulement les lignes correspondantes. Pour gauche rejoint, plusieurs requêtes est beaucoup mieux ... regardez l'indice de référence suivant, je l'ai fait:

  1. requête à l'unité de 5 joint

    query: 8.074508 secondes

    Taille de résultat: 2268000

  2. 5 requêtes consécutives

    temps de requête combinée: 0.00262 secondes

    Taille 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)

gauche se joint à utiliser de façon exponentielle plus de mémoire avec des données redondantes.

La limite de mémoire peut ne pas être aussi mauvais si vous ne faites une jointure de deux tables, mais en général trois ou plus et il devient une valeur de requêtes différentes.

Comme une note de côté, mon serveur MySQL est juste à côté de mon serveur d'application ... si le temps de connexion est négligeable. Si votre temps de connexion est dans les dernières secondes, alors peut-être il y a un avantage

Frank

En fait, je suis venu à cette question à la recherche d'une réponse moi-même, et après avoir lu les réponses, je ne peux qu'être d'accord que la meilleure façon de comparer DB requêtes performance est d'obtenir des chiffres réels, car il y a juste beaucoup de variables à pris en compte, mais aussi, je pense que la comparaison des chiffres entre les conduit à rien de bon dans presque tous les cas. Ce que je veux dire est que les chiffres doivent toujours être comparés à un nombre acceptable et certainement pas par rapport à l'autre.

Je peux comprendre si une façon de se dire 0,02 requêtes secondes et l'autre prend 20 secondes, c'est une énorme différence. Mais si une façon de se 0.0000000002 secondes l'interrogation, et l'autre prend 0,0000002 secondes? Dans les deux cas, d'une manière est une somme exorbitante 1000 fois plus rapide que l'autre, mais est-il vraiment dans le second cas encore « modique somme »?

En bout de ligne que je vois personnellement: si elle fonctionne bien, optez pour la solution facile

.

a fait un test rapide sélection d'une ligne d'une table de rangée 50 000 et se joindre à une ligne d'une table 100 000 de ligne. Au fond ressemblait à:

$id = mt_rand(1, 50000);
$row = $db->fetchOne("SELECT * FROM table1 WHERE id = " . $id);
$row = $db->fetchOne("SELECT * FROM table2 WHERE other_id = " . $row['other_id']);

vs

$id = mt_rand(1, 50000);
$db->fetchOne("SELECT table1.*, table2.*
    FROM table1
    LEFT JOIN table1.other_id = table2.other_id
    WHERE table1.id = " . $id);

Les deux méthode select a 3,7 secondes pour 50 000 lectures alors que le JOIN a pris 2.0 secondes sur mon ordinateur lent à domicile. INNER JOIN et LEFT JOIN n'a pas fait une différence. Obtention de plusieurs lignes (par exemple, en utilisant SET IN) a donné des résultats similaires.

Construire les deux requêtes et jointures séparées, alors le temps chacun d'eux -. Rien ne permet plus que des chiffres du monde réel

Alors encore mieux - ajouter « EXPLIQUER » au début de chaque requête. Cela vous indiquera combien de MySQL utilise les sous-requêtes pour répondre à votre demande de données, et le nombre de lignes numérisées pour chaque requête.

En fonction de la complexité de la base de données par rapport à la complexité des développeurs, il peut être plus simple à faire beaucoup d'appels SELECT.

Essayez d'exécuter quelques statistiques de base de données contre les deux JOIN et les multiples Selects. Voyez si dans votre environnement le JOIN est plus rapide / plus lent que le SELECT.

Et puis, si le changement à un JOIN signifierait un jour supplémentaire / semaine / mois de travail dev, je bâton avec plusieurs SELECTs

Cheers,

BLT

La vraie question est: faire ces enregistrements ont un one-to-one relation ou un à plusieurs relation

TLDR Réponse:

Si un à un, utilisez une déclaration JOIN.

Si un à plusieurs, utilisez un (ou plusieurs) des déclarations avec l'optimisation des SELECT code côté serveur.

Pourquoi et comment utiliser SELECT pour l'optimisation

<=> 'ing (avec plusieurs requêtes au lieu de jointures) sur un grand groupe d'enregistrements à partir d'un one-to-many produit une efficacité optimale, comme <=> ING a un problème de fuite de mémoire exponentielle. Prenez toutes les données, puis d'utiliser un langage de script côté serveur pour le tri:

SELECT * FROM Address WHERE Personid IN(1,2,3);

Résultats:

Address.id : 1            // First person and their address
Address.Personid : 1
Address.City : "Boston"

Address.id : 2            // First person's second address
Address.Personid : 1
Address.City : "New York"

Address.id : 3            // Second person's address
Address.Personid : 2
Address.City : "Barcelona"

Ici, je reçois tous les enregistrements, dans une instruction select. Cela vaut mieux que <=>, qui serait d'obtenir un petit groupe de ces documents, un à la fois, comme un sous-composante d'une autre requête. Ensuite, je parse avec le code côté serveur qui ressemble à ...

<?php
    foreach($addresses as $address) {
         $persons[$address['Personid']]->Address[] = $address;
    }
?>

Quand ne pas utiliser JOIN pour l'optimisation

<=> 'ing un grand groupe d'enregistrements à partir d'une seule à une relation avec un enregistrement unique produit une efficacité optimale par rapport à de multiples déclarations, l'un après <=> l'autre, qui obtiennent simplement le type d'enregistrement suivant .

Mais est inefficace quand <=> obtenir des enregistrements avec un à plusieurs.

Exemple:. La base de données blogs dispose de 3 tables d'intérêt, Blogpost, Tag et commentaires

SELECT * from BlogPost
LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id
LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;

S'il y a 1 blogpost, 2 balises et 2 commentaires, vous obtiendrez des résultats tels que:

Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,

Remarquez comment chaque enregistrement est reproduit. D'accord, donc, 2 commentaires et 2 balises est de 4 lignes. Et si nous avons 4 commentaires et 4 balises? Vous ne recevez pas 8 rangs - vous obtenez 16 lignes:

Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag1, comment3,
Row4: tag1, comment4,
Row5: tag2, comment1,
Row6: tag2, comment2,
Row7: tag2, comment3,
Row8: tag2, comment4,
Row9: tag3, comment1,
Row10: tag3, comment2,
Row11: tag3, comment3,
Row12: tag3, comment4,
Row13: tag4, comment1,
Row14: tag4, comment2,
Row15: tag4, comment3,
Row16: tag4, comment4,

Ajoutez d'autres tables, plus de disques, etc., et le problème se gonfle rapidement à des centaines de lignes qui sont toutes pleines de la plupart du temps données redondantes.

Qu'est-ce que ces doublons vous coûter? Mémoire (dans le serveur SQL et le code qui tente de supprimer les doublons) et les ressources de réseau (entre le serveur SQL et votre serveur de code).

Source: https: //dev.mysql .com / doc / refman / 8.0 / fr / emboîtée-join-optimization.html ; https://dev.mysql.com/doc/workbench/ fr / wb-relation tools.html

Dans mon expérience, je l'ai trouvé 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 d'une autre application, telles que PHP, il y a l'argument d'un voyage au serveur sur un grand nombre.

Il existe d'autres moyens de limiter le nombre de déplacements effectués sur le serveur et toujours exécuter plusieurs requêtes qui sont souvent non seulement plus rapide, mais aussi rendre l'application plus facile à lire -. Par exemple mysqli_multi_query

Je ne suis pas novice en matière de SQL, je pense qu'il ya une tendance pour les développeurs, en particulier juniors de passer beaucoup de temps à essayer d'écrire très intelligent parce qu'ils regardent rejoint intelligents, alors qu'il existe effectivement des moyens intelligents pour extraire les données qui ont l'air simple.

Le dernier paragraphe est une opinion personnelle, mais j'espère que cela aide. Je suis d'accord avec les autres mais qui disent que vous devriez référence. Aucune de ces approches est une balle d'argent.

Cette question est vieux, mais il manque quelques points de repère. Je benchmarkée REJOIGNEZ contre ses 2 concurrents:

  • N + 1 requêtes
  • 2 requêtes, la seconde en utilisant un WHERE IN(...) ou équivalent

Le résultat est clair: sur MySQL, est JOIN beaucoup plus rapide. N + 1 requêtes peuvent déposer les performances d'une application radicalement:

C'est, à moins que vous sélectionnez un grand nombre d'enregistrements qui pointent vers un très petit nombre de dossiers distincts, étrangers. Voici un point de référence pour le cas extrême:

Il est très peu probable de se produire dans une application typique, à moins que vous vous joignez à une relation -À-beaucoup, dans ce cas, la clé étrangère est sur l'autre table, et vous dupliquer les principales données de la table à plusieurs reprises.

emporter:

  • Pour * -à relations individuelles, utilisez toujours <=>
  • Pour * -à-plusieurs, une deuxième requête peut plus rapide

Voir mon article sur Medium plus d'informations.

est-il plus rapide en termes de débit? Probablement. Mais elle a aussi bloque potentiellement des objets de base de données plus à un moment (en fonction de votre base de données et votre schéma) et diminue ainsi la concurrence. Dans mon expérience, les gens sont souvent induire en erreur par l'argument « allers-retours moins la base de données », alors qu'en réalité la plupart des systèmes OLTP où la base de données est sur le même réseau local, le véritable goulot d'étranglement est rarement le réseau.

Voici un lien avec 100 requêtes utiles, celles-ci sont testés dans la base de données Oracle SQL, mais rappelez-vous est une norme, ce qui diffère entre Oracle, MS SQL Server, MySQL et d'autres bases de données sont le dialecte SQL:

http://javaforlearn.com/100-sql-queries-learn/

Il y a plusieurs facteurs qui signifie qu'il n'y a pas de réponse binaire. La question de ce qui est le mieux pour la performance dépend de votre environnement. Soit dit en passant, si votre seule sélection avec un identifiant n'est pas sous-seconde, quelque chose peut-être pas avec votre configuration.

La vraie question à se poser est comment voulez-vous accéder aux données. Simple soutien choisit la liaison tardive. Par exemple, si vous ne souhaitez que l'information des employés, vous pouvez choisir la table Employés. Les relations de clé étrangère peuvent être utilisées pour récupérer des ressources connexes à une date ultérieure et au besoin. Selects auront déjà une clé pour pointer vers elles doivent donc être extrêmement rapide, et il vous suffit de récupérer ce dont vous avez besoin. La latence du réseau doit toujours être pris en compte.

Rejoint récupérera toutes les données à la fois. Si vous générez un rapport ou d'alimenter une grille, cela peut être exactement ce que vous voulez. Compilé et optomized jointures vont tout simplement être plus rapide que simple dans ce scénario sélectionne. Rappelez-vous, Ad-hoc se joint peut ne pas être aussi rapide - vous devez les compiler (dans une procédure stockée). La réponse de la vitesse dépend du plan d'exécution, qui détaille exactement quelles mesures le SGBD prend pour récupérer les données.

Si vous utilisez une jointure est d'abord et avant tout de savoir si une jointure est logique . Seulement à ce moment est la performance même quelque chose à considérer, comme presque tous les autres cas entraînera beaucoup pire performance.

Les écarts de rendement seront en grande partie liée à la façon dont liés à l'information que vous vous interrogez pour est. Travail se joint, et ils sont vite quand les données sont liées et correctement des trucs d'index, mais ils ne se traduisent souvent par 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, de les coller dans une seule requête entraînera dans ce qu'on appelle un produit cartésien (essentiellement, toutes les combinaisons possibles de lignes), ce qui est presque jamais ce que vous voulez.

Ceci est souvent causée par plusieurs-à-un à plusieurs. Par exemple, la réponse HoldOffHunger mentionné une seule requête pour les postes, les balises et les commentaires. Les commentaires sont liés à un poste, comme les balises ... mais les balises ne sont pas liées aux commentaires.

+------------+     +---------+     +---------+
|  comment   |     |   post  |     |  tag    |
|------------|*   1|---------|1   *|---------|
| post_id    |-----| post_id |-----| post_id |
| comment_id |     | ...     |     | tag_id  |
| user_id    |     |         |     | ...     |
| ...        |     |         |     | ...     |
+------------+     +---------+     +---------+

Dans ce cas, il est clairement mieux pour que cela soit au moins deux requêtes distinctes. Si vous essayez de joindre les étiquettes et les commentaires, parce qu'il n'y a pas de relation directe entre les deux, vous vous retrouvez avec toutes les combinaisons possibles de l'étiquette et de commentaires. many * many == manymany. Mis à part cela, étant donné que les messages et les étiquettes ne sont pas liés, vous pouvez faire ces deux requêtes en parallèle, conduisant à un gain potentiel.

Considérons un autre scénario, bien que. Vous voulez que les commentaires attachés à un poteau et la coordonnées de commenters

 +----------+     +------------+     +---------+
 |   user   |     |  comment   |     |   post  |
 |----------|1   *|------------|*   1|---------|
 | user_id  |-----| post_id    |-----| post_id |
 | username |     | user_id    |     | ...     |
 | ...      |     | ...        |     +---------+
 +----------+     +------------+

est où vous devriez envisager une jointure. En plus d'être beaucoup plus naturelle requête, la plupart des systèmes de bases de données MySQL (y compris) ont beaucoup de gens intelligents ont mis beaucoup de travail dans l'optimisation des requêtes comme il. Pour des requêtes distinctes, puisque chaque requête dépend des résultats de la précédente, les requêtes ne peuvent être effectuées en parallèle, et le temps total devient pas seulement le temps d'exécuter des requêtes réelles, mais aussi le temps passé à chercher des résultats, tamiser à travers eux pour les ID de la requête suivante, reliant ensemble des lignes, etc.

Oui, une requête à l'aide REJOINT serait plus rapide. Bien que sans connaître les rapports des tables que vous interrogez, la taille de votre ensemble de données, ou lorsque les clés primaires sont, il est presque impossible de dire combien plus vite.

Pourquoi ne pas tester les deux scénarios, alors vous saurez sûr ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top