2009-03-22 4 views
45

Der Effekt des Ausgebens eines inneren Joins entspricht dem Angeben eines Kreuz-Join mit der Join-Bedingung in der WHERE-Klausel. Ich habe festgestellt, dass viele Leute in meinem Unternehmen Cross Joins verwenden, wo ich interne Joins verwenden würde. Ich habe keinen signifikanten Leistungszuwachs bemerkt, nachdem ich einige dieser Abfragen geändert hatte, und ich fragte mich, ob es nur ein Zufall war oder ob das DBMS solche Probleme transparent optimiert (in unserem Fall MySql). Und hier ein konkretes Beispiel für die Diskussion:Leistung von innerem Join im Vergleich zu Kreuz Join

SELECT User.* 
FROM User, Address 
WHERE User.addressId = Address.id; 

SELECT User.* 
FROM User 
INNER JOIN Address ON (User.addressId = Address.id); 
+6

Die erste ist nicht ANSI SQL. Ich weiß, dass Microsoft empfohlen hat, zu der Syntax Ihres zweiten Beispiels zu wechseln. MySQL kann jetzt dasselbe tun, wenn sie Unternehmen sind. Auch das erste ist kein Cross-Join. Ein Cross-Join wäre, wenn Sie die WHERE-Klausel weggelassen haben. – WakeUpScreaming

+2

Warum ist es nicht ANSI SQL? – soulmerge

+4

Die Querverknüpfung, die Sie aufrufen, ist eine ältere Syntax. Wir Dinosaurier :) neigen dazu, es zu benutzen. Die innere Join-Syntax wurde als Teil des SQL 92 (IIRC) -Standards vereinbart. Seither haben sich die Anbieter auf die Unterstützung der meisten Anbieter hinbewegt, die beide unterstützen. Daher ist es nicht ANSI, weil es nicht in der Dokumentation ist. – Karl

Antwort

43

Kreuzverknüpfungen erzeugen Ergebnisse, die aus jeder Kombination von Zeilen aus zwei oder mehr Tabellen bestehen. Das heißt, wenn Tabelle A 6 Zeilen und Tabelle B 3 Zeilen hat, ergibt ein Kreuz-Join 18 Zeilen. Es besteht keine Beziehung zwischen den beiden Tabellen - Sie produzieren buchstäblich nur jede mögliche Kombination.

Bei einem inneren Join werden Spaltenwerte aus einer Zeile einer Tabelle mit Spaltenwerten aus einer anderen Zeile einer anderen (oder derselben) Tabelle kombiniert, um eine einzelne Datenzeile zu bilden.

Wenn eine WHERE-Klausel zu einem Kreuz-Join hinzugefügt wird, verhält es sich wie ein Inner-Join, da das WHERE einen Begrenzungsfaktor auferlegt.

Solange Ihre Fragen durch den gesunden Menschenverstand und herstellerspezifischen einhalten, denke ich gerne an die Entscheidung, welche Art von Join zu verwenden, um eine einfache Frage des Geschmacks zu sein.

14

Verwenden EXPLAIN den Abfrageplan für beide Abfragen betrachten, und sehen, ob es einen Unterschied gibt. Möglicherweise wird MySQL in beiden Fällen denselben Ausführungsplan verwenden. Ich benutze die Syntax hauptsächlich, weil es viel klarer ist.

23

Es gibt keinen Unterschied anders als der innere Join ist viel klarer, weil es den Join definiert, verlassen die Where-Klausel als die eigentliche einschränkende Bedingung.

1

Die Reihenfolge, in der Sie Tabellen beitreten oder Ihre ON/WHERE-Bedingungen setzen, sollte keine Rolle spielen.

Der Abfrageoptimierer sollte auf jeden Fall die besten optimieren und nutzen (und chosing wie man am besten die Daten filtern, wo etc starten)

Wie viele andere aber, schlage ich Syntax der INNER JOIN verwenden, da es macht die Dinge viel lesbarer, es ist mit der Syntax von LEFT- oder FULL-Joins auch transparenter.

Es gibt eine etwas Behausung Text über sie hier: http://linus.brimstedt.se/?/article/articleview/SQL Syntax

/B

2

Das erste Beispiel ist funktionell das gleiche wie das zweite Beispiel. Diese Syntax sollte jedoch aus mehreren Gründen vermieden werden. Erstens ist es viel einfacher, versehentlich einen Kreuz-Join zu erhalten, wenn diese Syntax verwendet wird, besonders wenn es mehrere Joins in der Tabelle gibt. Wenn Sie eine Menge dieser Art von Abfrage mit dem Schlüsselwort distinct sehen, haben Sie wahrscheinlich jemanden, der versucht, die Cross-Joins zu beheben.

Als Nächstes wird die linke und rechte Joinsyntax mit dem älteren Stil nicht mehr unterstützt und nicht mehr unterstützt. Außerdem funktioniert es jetzt sowieso nicht richtig. Manchmal interpretiert es die äußere Verknüpfung falsch und sendet die falsche Ergebnismenge zurück. Daher sollten alle Anfragen, die Sie verwenden, = oder = in der WHERE-Klausel sofort ersetzt werden.

Drittens sind ANSI-Standard-Joins leichter zu verstehen und zu pflegen.Ein Verständnis von Joins ist eine der kritischsten Grundfertigkeiten, die jeder, der eine relationale Datenbank anfragt, haben muss. Es ist meine Erfahrung, dass einige Leute, die den älteren Stil verwenden, Joins und ihre Arbeitsweise nicht wirklich verstehen und somit Abfragen schreiben, die nicht das tun, was sie eigentlich wollten.

10

Ich finde, dass Arbeitsplätze, die die erste Syntax zulassen (kommagetrennte Tabellen), tendenziell eine erhebliche Zeit in Anspruch nehmen, um Fälle zu debuggen, in denen mehr Zeilen zurückgegeben werden als beabsichtigt. Unbeabsichtigte Kreuzverbindungen sind der Fluch eines Systems und können sogar die am besten abgestimmte Datenbank in die Knie zwingen. Es hat unser Pre-Prod-System im vergangenen Jahr mindestens zwei Mal zum Stillstand gebracht.

Die zweite Syntax (Joinsyntax) zwingt den Writer, darüber nachzudenken, wie die Tabellen zuerst zusammengefügt werden, und gibt dann nur die interessanten Zeilen zurück. Es ist unmöglich, versehentlich einen Cross-Join mit dieser Syntax durchzuführen, und somit wird die Gefahr von versehentlich fehlerhaften Abfragen reduziert.

Abgesehen von diesem Problem, habe ich nie einen Geschwindigkeitsunterschied zwischen den beiden Syntaxen in irgendwelchen Systemen bemerkt, die ich gehabt habe.

1

Ein weiterer Vorteil der ersten Syntax ist, dass Sie in Ihrer einschränkenden Bedingung allgemeiner sein können. Nicht nur Gleichheit.

Aber wenn Sie Gleichheit verwenden, warum dem Optimierer vertrauen? Stellen Sie sicher, dass es nicht zuerst den Kreuz-Join erzeugt und dann die Zeilen entfernt. Benutze den zweiten.

+0

Könnte für MySQL wahr sein, ich weiß es nicht. Aber in SQL-Server können Sie andere Bedingungen als Gleichheit auf der rechten Seite des "An" setzen. –

+0

Sie können das gleiche in MySQL tun. –

-1

Seit dem Beginn der Zeit werden Optimierer um klassische restrict-project-cartesian Produkt-Syntax gebaut. Praktisch alle Anbieter kopierten das Design, das von System R entwickelt wurde. Widerwillig nahmen die Anbieter die "neueste und beste" ANSI-Syntax an und rüsteten ihre SQL-Ausführungs-Engines nach. Im Gegensatz zu dem, was Marketingbroschüre Ihnen sagen kann ("verwenden Sie die neueste Syntax"), wurde nicht viel auf der physischen Implementierungsebene geändert: es ist immer noch [indiziert] verschachtelte Schleifen oder Hash- oder Sortier-Merge-Joins. Daher gibt es keine Grundlage, um die Überlegenheit einer Syntax gegenüber der anderen anzunehmen.

Nach meinem persönlichen Geschmack ist die neue Syntax redundant, laut, und inconsistent. Um vom Komitee genehmigt zu werden, "gehen Sie in jeden Park in jeder Stadt und Sie werden keine Statue des Komitees finden".

+0

Die Verwendung impliziter Joins ist ein SQL-Antipattern. Es ist zufälligen Kreuz Joins, es ist schwieriger zu pflegen, vor allem, wenn Sie zu einem bestimmten Zeitpunkt zu Outer Joins wechseln müssen (Sie sollten nicht die beiden und die implizite Syntax Outer Join zumindest in einigen Datenbanken nicht richtig funktioniert irgendwie mischen). Wenn Sie tatsächlich einen Cross-Join möchten, gibt es keine Möglichkeit zu sagen, ob das wahr ist oder ob Sie unter dem zufälligen Cross-Join-Problem leiden. So Absicht ist nicht klar. Das ist nur eine schlechte Übung. – HLGEM

0

beiden Abfragen gibt denselben Ausgang Erklären

mysql> explain select * from t T1, t T2 where T1.ID=T2.ID; 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| 1 | SIMPLE  | T1 | ALL | PRIMARY  | NULL | NULL | NULL | 3 |        | 
| 1 | SIMPLE  | T2 | ALL | PRIMARY  | NULL | NULL | NULL | 3 | Using where; Using join buffer | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
2 rows in set (0.00 sec) 

mysql> explain select * from t T1 join t T2 on T1.ID=T2.ID; 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| 1 | SIMPLE  | T1 | ALL | PRIMARY  | NULL | NULL | NULL | 3 |        | 
| 1 | SIMPLE  | T2 | ALL | PRIMARY  | NULL | NULL | NULL | 3 | Using where; Using join buffer | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
2 rows in set (0.00 sec) 

Aber mit innerem Join-Syntax als mehr klarer und präziser zu bevorzugen ist. Mysql kann Links und Rechts Join-Abfragen intern optimieren, um weniger Daten im Vergleich zu Cross Join auszuwählen.