it-swarm.com.de

JOIN-Abfragen im Vergleich zu mehreren Abfragen

Sind JOIN-Abfragen schneller als mehrere Abfragen? (Sie führen Ihre Hauptabfrage aus, und Sie führen dann viele andere SELECTs aus, die auf den Ergebnissen Ihrer Hauptabfrage basieren.)

Ich frage, weil die Teilnahme an ihnen das Design meiner Anwendung VIEL erschweren würde

Wenn sie schneller sind, kann sich jemand sehr grob annähern, um wie viel? Wenn es 1,5x ist, ist es mir egal, aber wenn es 10x ist, denke ich, ist es das auch.

156
Thomas Bonini

Dies ist viel zu vage, um Ihnen eine Antwort zu geben, die für Ihren speziellen Fall relevant ist. Es hängt von vielen Dingen ab. Jeff Atwood (Gründer dieser Seite) tatsächlich schrieb darüber . In den meisten Fällen ist es jedoch in der Regel schneller, einen Trip als mehrere durchzuführen, wenn Sie über die richtigen Indizes verfügen und Ihre JOINs ordnungsgemäß ausführen.

71

Für innere Verknüpfungen ist eine einzelne Abfrage sinnvoll, da Sie nur übereinstimmende Zeilen erhalten. Für Links-Joins sind Mehrfachabfragen viel besser. Schauen Sie sich den folgenden Benchmark an, den ich erstellt habe:

  1. Einzelabfrage mit 5 Joins

    abfrage: 8.074508 Sekunden

    ergebnisgröße: 2268000

  2. 5 Abfragen hintereinander

    kombinierte Abfragezeit: ,00262 Sekunden

    ergebnisgröße: 165 (6 + 50 + 7 + 12 + 90)

.

Beachten Sie, dass wir in beiden Fällen die gleichen Ergebnisse erhalten (6 x 50 x 7 x 12 x 90 = 2268000)

left Joins belegen exponentiell mehr Speicher mit redundanten Daten.

Das Speicherlimit ist möglicherweise nicht so schlecht, wenn Sie nur einen Join von zwei Tabellen ausführen, im Allgemeinen jedoch drei oder mehr, und es sind unterschiedliche Abfragen wert.

Nebenbei bemerkt, mein MySQL-Server befindet sich direkt neben meinem Anwendungsserver ... daher ist die Verbindungszeit vernachlässigbar. Wenn Ihre Verbindungszeit in Sekunden liegt, gibt es möglicherweise einen Vorteil

Frank

86
Frank Forte

Eigentlich bin ich auf diese Frage gekommen, um eine Antwort zu finden, und nachdem ich die gegebenen Antworten gelesen habe, kann ich nur zustimmen, dass der beste Weg, die Leistung von DB-Abfragen zu vergleichen, darin besteht, reale Zahlen zu erhalten, da nur zu viele Variablen zu berücksichtigen sind ABER ich denke auch, dass das Vergleichen der Zahlen zwischen ihnen in fast allen Fällen zu nichts Gutes führt. Was ich meine ist, dass die Zahlen immer mit einer akzeptablen Zahl verglichen und definitiv nicht miteinander verglichen werden sollten.

Ich kann verstehen, wenn eine Art der Abfrage beispielsweise 0,02 Sekunden und die andere 20 Sekunden dauert, ist das ein enormer Unterschied. Was aber, wenn eine Art der Abfrage 0,0000000002 Sekunden und die andere 0,0000002 Sekunden dauert? In beiden Fällen ist eine Art und Weise 1000-mal schneller als die andere, aber ist es wirklich im zweiten Fall immer noch "hüpfen"?

Fazit, wie ich es persönlich sehe: Wenn es gut abschneidet, entscheiden Sie sich für die einfache Lösung.

20

Wir haben einen kurzen Test durchgeführt, bei dem eine Zeile aus einer Tabelle mit 50.000 Zeilen ausgewählt und eine Zeile aus einer Tabelle mit 100.000 Zeilen hinzugefügt wurde. Grundsätzlich sah es so aus:

$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);

Die Zwei-Auswahl-Methode benötigte 3,7 Sekunden für 50.000 Lesevorgänge, während der JOIN-Vorgang auf meinem langsamen Heimcomputer 2,0 Sekunden dauerte. INNER JOIN und LEFT JOIN machten keinen Unterschied. Das Abrufen mehrerer Zeilen (z. B. unter Verwendung von IN SET) ergab ähnliche Ergebnisse.

13
levans

Erstellen Sie sowohl separate Abfragen als auch Verknüpfungen, und messen Sie dann die einzelnen Abfragen - nichts hilft mehr als Zahlen aus der realen Welt.

Dann noch besser - fügen Sie "EXPLAIN" am Anfang jeder Abfrage ein. Hier erfahren Sie, wie viele Unterabfragen MySQL verwendet, um Ihre Datenanforderung zu beantworten, und wie viele Zeilen für jede Abfrage gescannt wurden.

8

Abhängig von der Komplexität der Datenbank im Vergleich zur Komplexität des Entwicklers kann es einfacher sein, viele SELECT-Aufrufe auszuführen.

Versuchen Sie, einige Datenbankstatistiken sowohl für JOIN als auch für Multiple SELECTS auszuführen. Überprüfen Sie, ob in Ihrer Umgebung JOIN schneller/langsamer als SELECT ist.

Andererseits würde ich mich an mehrere SELECTs halten, wenn eine Änderung in JOIN einen zusätzlichen Tag/eine Woche/einen zusätzlichen Monat Entwicklungsarbeit bedeuten würde

Prost,

BLT

7
glasnt

Die eigentliche Frage ist: Haben diese Datensätze eine Eins-zu-Eins-Beziehung oder eine Eins-zu-Viele-Beziehung ?

TLDR-Antwort:

Verwenden Sie bei Eins-zu-Eins eine JOIN - Anweisung.

Bei Eins-zu-Viele verwenden Sie eine (oder mehrere) SELECT - Anweisungen mit serverseitiger Codeoptimierung.

Warum und wie SELECT zur Optimierung verwendet wird

SELECT 'ing (mit mehreren Abfragen anstelle von Verknüpfungen) für eine große Gruppe von Datensätzen basierend auf einer Eins-zu-Viele-Beziehung führt zu einer optimalen Effizienz, da JOIN' ing ein exponentielles Speicherverlustproblem aufweist . Holen Sie sich alle Daten und sortieren Sie sie mithilfe einer serverseitigen Skriptsprache aus:

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

Ergebnisse:

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"

Hier bekomme ich alle Datensätze in einer ausgewählten Anweisung. Dies ist besser als JOIN, bei dem eine kleine Gruppe dieser Datensätze einzeln als Unterkomponente einer anderen Abfrage abgerufen wird. Dann analysiere ich es mit serverseitigem Code, der ungefähr so ​​aussieht ...

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

Wenn JOIN nicht für die Optimierung verwendet werden soll

JOIN Wenn eine große Gruppe von Datensätzen basierend auf einer Eins-zu-Eins-Beziehung mit einem einzelnen Datensatz erstellt wird, ergibt sich eine optimale Effizienz im Vergleich zu mehreren SELECT - Anweisungen, die einfach den Wert erhalten nächster Datensatztyp.

JOIN ist jedoch ineffizient, wenn Datensätze mit einer Eins-zu-Viele-Beziehung abgerufen werden.

Beispiel: Die Datenbank "Blogs" enthält drei interessante Tabellen: "Blogpost", "Tag" und "Kommentar".

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

Wenn es 1 Blogpost, 2 Tags und 2 Kommentare gibt, erhalten Sie Ergebnisse wie:

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

Beachten Sie, wie jeder Datensatz dupliziert wird. Okay, also 2 Kommentare und 2 Tags sind 4 Zeilen. Was ist, wenn wir 4 Kommentare und 4 Tags haben? Sie erhalten keine 8 Zeilen - Sie erhalten 16 Zeilen:

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,

Wenn Sie mehr Tabellen, mehr Datensätze usw. hinzufügen, steigt das Problem schnell auf Hunderte von Zeilen an, die alle mit größtenteils redundanten Daten gefüllt sind.

Was kosten Sie diese Duplikate? Arbeitsspeicher (auf dem SQL Server und der Code, der versucht, die Duplikate zu entfernen) und Netzwerkressourcen (zwischen SQL Server und Ihrem Codeserver).

Quelle: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html

6
HoldOffHunger

Diese Frage ist alt, aber es fehlen einige Benchmarks. Ich habe JOIN mit seinen 2 Konkurrenten verglichen:

  • N + 1 Abfragen
  • 2 Abfragen, die zweite mit einer WHERE IN(...) oder einer Entsprechung

Das Ergebnis ist klar: Unter MySQL ist JOIN viel schneller. N + 1-Abfragen können die Leistung einer Anwendung drastisch beeinträchtigen:

JOIN vs WHERE IN vs N+1

Das heißt, es sei denn, Sie wählen viele Datensätze aus, die auf eine sehr kleine Anzahl unterschiedlicher ausländischer Datensätze verweisen. Hier ist ein Maßstab für den Extremfall:

JOIN vs N+1 - all records pointing to the same foreign record

Dies ist in einer typischen Anwendung sehr unwahrscheinlich, es sei denn, Sie treten einer-zu-vielen-Beziehung bei. In diesem Fall befindet sich der Fremdschlüssel in der anderen Tabelle und Sie duplizieren die Daten der Haupttabelle mehrmals.

Wegbringen:

  • Verwenden Sie für * -to-one-Beziehungen immer JOIN
  • Bei * -zu-vielen Beziehungen kann eine zweite Abfrage schneller sein

Siehe mein Artikel auf Medium für weitere Informationen.

5
Benjamin

Nach meiner Erfahrung ist es normalerweise schneller, mehrere Abfragen auszuführen, insbesondere beim Abrufen großer Datenmengen.

Bei der Interaktion mit der Datenbank von einer anderen Anwendung wie PHP aus gibt es das Argument, dass ein Trip zum Server über mehrere hinweg geht.

Es gibt andere Möglichkeiten, um die Anzahl der Fahrten zum Server zu begrenzen und dennoch mehrere Abfragen auszuführen, die häufig nicht nur schneller sind, sondern auch die Lesbarkeit der Anwendung verbessern - beispielsweise mysqli_multi_query.

Ich bin kein Anfänger, wenn es um SQL geht. Ich glaube, Entwickler, insbesondere Junioren, verbringen viel Zeit damit, sehr clevere Joins zu schreiben, weil sie schlau aussehen, während es tatsächlich clevere Möglichkeiten gibt, Daten zu extrahieren, die aussehen einfach.

Der letzte Absatz war eine persönliche Meinung, aber ich hoffe, das hilft. Ich stimme jedoch den anderen zu, die sagen, Sie sollten ein Benchmarking durchführen. Kein Ansatz ist eine Silberkugel.

5
A Boy Named Su

Wird es schneller im Durchsatz sein? Wahrscheinlich. Es werden jedoch möglicherweise auch mehr Datenbankobjekte gleichzeitig gesperrt (abhängig von Ihrer Datenbank und Ihrem Schema), wodurch die Parallelität verringert wird. Nach meiner Erfahrung werden die Leute oft durch das Argument "weniger Datenbank-Roundtrips" irregeführt, wenn in der Realität auf den meisten OLTP) Systemen, in denen sich die Datenbank im selben LAN befindet, der eigentliche Engpass selten das Netzwerk ist.

3
Ramon

Hier ist ein Link mit 100 nützlichen Abfragen, diese sind in Oracle-Datenbanken getestet, aber denken Sie daran, SQL ist ein Standard, was zwischen Oracle, MS SQL Server, MySQL und anderen Datenbanken den SQL-Dialekt unterscheidet:

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

2
S. Mayol

Es gibt mehrere Faktoren, was bedeutet, dass es keine binäre Antwort gibt. Die Frage, was für die Leistung am besten ist, hängt von Ihrer Umgebung ab. Übrigens: Wenn Ihre Einzelauswahl mit einem Bezeichner nicht unter der Sekunde liegt, liegt möglicherweise ein Fehler in Ihrer Konfiguration vor.

Die eigentliche Frage ist, wie Sie auf die Daten zugreifen möchten. Single Selects unterstützen die späte Bindung. Wenn Sie beispielsweise nur Mitarbeiterinformationen wünschen, können Sie diese in der Tabelle "Mitarbeiter" auswählen. Die Fremdschlüsselbeziehungen können verwendet werden, um verwandte Ressourcen zu einem späteren Zeitpunkt und nach Bedarf abzurufen. Die Selects haben bereits einen Schlüssel, auf den sie zeigen müssen, sodass sie extrem schnell sein sollten und Sie nur das abrufen müssen, was Sie benötigen. Die Netzwerklatenz muss immer berücksichtigt werden.

Joins rufen alle Daten gleichzeitig ab. Wenn Sie einen Bericht erstellen oder ein Raster auffüllen, ist dies möglicherweise genau das, was Sie möchten. Kompilierte und optimierte Joins sind in diesem Szenario einfach schneller als einzelne Auswahlen. Denken Sie daran, dass Ad-hoc-Verknüpfungen möglicherweise nicht so schnell sind - Sie sollten sie kompilieren (in einem gespeicherten Prozess). Die Geschwindigkeitsantwort hängt vom Ausführungsplan ab, in dem genau angegeben ist, welche Schritte das DBMS zum Abrufen der Daten ausführt.

1
dr.lockett

Ob Sie einen Join verwenden sollten, hängt in erster Linie davon ab, ob ein Join sinnvoll ist . Nur zu diesem Zeitpunkt ist die Leistung überhaupt zu berücksichtigen, da in fast allen anderen Fällen die Leistung erheblich schlechter ausfällt.

Leistungsunterschiede hängen größtenteils davon ab, in welchem ​​Zusammenhang die von Ihnen abgefragten Informationen stehen. Verknüpfungen funktionieren und sind schnell, wenn die Daten in Beziehung stehen und Sie die Daten korrekt indizieren, aber sie führen häufig zu Redundanz und manchmal zu mehr Ergebnissen als erforderlich. Und wenn Ihre Datensätze nicht in direktem Zusammenhang stehen, führt das Festhalten an ihnen in einer einzelnen Abfrage zu einem so genannten kartesischen Produkt (im Grunde genommen alle möglichen Reihenkombinationen), das so gut wie nie Ihren Wünschen entspricht.

Dies wird häufig durch viele-zu-eins-zu-viele-Beziehungen verursacht. Beispiel: Antwort von HoldOffHunger erwähnte eine einzelne Abfrage nach Posts, Tags und Kommentaren. Kommentare beziehen sich auf einen Beitrag, ebenso wie Tags ..., aber Tags haben nichts mit Kommentaren zu tun.

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

In diesem Fall ist es eindeutig besser, wenn es sich um mindestens zwei separate Abfragen handelt. Wenn Sie versuchen, Tags und Kommentare zu verknüpfen, da keine direkte Beziehung zwischen beiden besteht, erhalten Sie jede mögliche Kombination aus Tag und Kommentar. many * many == manymany. Da Posts und Tags nicht miteinander verknüpft sind, können Sie diese beiden Abfragen auch parallel ausführen, was zu einem potenziellen Gewinn führt.

Betrachten wir jedoch ein anderes Szenario: Sie möchten, dass die Kommentare an einen Beitrag angehängt werden und die Kontaktinformationen der Kommentatoren.

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

Hier sollten Sie einen Join in Betracht ziehen. Abgesehen davon, dass es sich um eine viel natürlichere Abfrage handelt, haben die meisten Datenbanksysteme (einschließlich MySQL) viele clevere Leute, die viel harte Arbeit in die Optimierung von Abfragen gesteckt haben. Bei separaten Abfragen können die Abfragen nicht parallel ausgeführt werden, da jede Abfrage von den Ergebnissen der vorherigen Abfrage abhängt. Die Gesamtzeit entspricht nicht nur der tatsächlichen Ausführungszeit der Abfragen, sondern auch der Zeit, die für das Abrufen der Ergebnisse und das Sieben aufgewendet wurde durch sie nach IDs für die nächste Abfrage, Verknüpfen von Zeilen usw.

1
cHao

Ja, eine Abfrage mit JOINS wäre schneller. Obwohl Sie die Beziehungen der Tabellen, die Sie abfragen, die Größe Ihres Datasets oder die Position der Primärschlüssel nicht kennen, können Sie kaum sagen, wie viel schneller Sie sind.

Warum testen Sie nicht beide Szenarien, dann wissen Sie sicher ...

0
Mathew