Die eigentliche Frage ist: Haben diese Datensätze eine Eins-zu-Eins-Beziehung oder eine Eins-zu-Viele-Beziehung ?
TLDR Antwort:
Wenn eins zu eins, verwenden Sie eine JOIN
Anweisung.
Verwenden Sie bei Eins-zu-Viele eine (oder mehrere) SELECT
Anweisungen mit serverseitiger Codeoptimierung.
Warum und wie SELECT zur Optimierung verwendet wird
SELECT
Das Erstellen (mit mehreren Abfragen anstelle von Verknüpfungen) für eine große Gruppe von Datensätzen, die auf einer Eins-zu-Viele-Beziehung basieren, führt zu einer optimalen Effizienz, da JOIN
das Problem mit einem exponentiellen Speicherverlust verbunden ist. Holen Sie sich alle Daten und sortieren Sie sie mit 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 erhalte ich alle Datensätze in einer Select-Anweisung. Dies ist besser als JOIN
, wenn 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;
}
?>
Wann sollte JOIN nicht zur Optimierung verwendet werden?
JOIN
Wenn eine große Gruppe von Datensätzen auf der Grundlage einer Eins-zu-Eins-Beziehung zu einem einzelnen Datensatz erstellt wird, ergibt sich eine optimale Effizienz im Vergleich zu mehreren aufeinanderfolgenden SELECT
Anweisungen, die einfach den nächsten Datensatztyp erhalten.
Ist JOIN
aber ineffizient, wenn Datensätze mit einer Eins-zu-Viele-Beziehung abgerufen werden.
Beispiel: Die Datenbank Blogs enthält 3 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 folgende Ergebnisse:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,
Beachten Sie, wie jeder Datensatz dupliziert wird. Okay, 2 Kommentare und 2 Tags sind 4 Zeilen. Was ist, wenn wir 4 Kommentare und 4 Tags haben? Sie erhalten nicht 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? Speicher (im 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