Explizite oder implizite SQL-Verknüpfungen

399

Gibt es einen Effizienzunterschied zwischen einer expliziten und einer impliziten inneren Verknüpfung? Zum Beispiel:

SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;

vs.

SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;
dmanxiii
quelle
11
Gute Frage. Ich bin gespannt, warum der explizite Join überhaupt verwendet wird. Ist es nicht möglich, alle Abfragen ohne sie durchzuführen?
Andrew
6
Verwenden Sie das Schlüsselwort EXPLAIN, um den Unterschied zwischen den beiden Abfragen zu ermitteln. Verwenden Sie JOIN und sehen Sie den Unterschied. Wenn Sie in einer Tabelle mehr als 100.000 Datensätze versuchen, können Sie den Unterschied erkennen ...
Jeyanth Kumar
@andrew Meine Frage war eigentlich, ob impliziter Join eine Form von "Hack" war (wie in "Eine Abfrage mit mehr als einer Tabelle, die keinen Join verwendet? Das ist ein Hack, nicht
wahr
3
Sie sind unterschiedlich, implizite Verknüpfungen werden Sie von Zeit zu Zeit überraschen, wenn Sie mit Nullwerten arbeiten. Verwenden Sie explizite Verknüpfungen und vermeiden Sie Fehler, die auftreten, wenn "nichts geändert wird!"
BlackTigerX
1
Es gibt keinen Unterschied. ,ist CROSS JOINmit lockerer Bindung & INNER JOINist CROSS JOINmit ONgleicher WHEREaber engerer Bindung. Für die Ausführung ist wichtig, wie das DBMS Abfragen optimiert.
Philipxy

Antworten:

132

In Bezug auf die Leistung sind sie genau gleich (zumindest in SQL Server).

PS: Beachten Sie, dass die IMPLICIT OUTER JOINSyntax seit SQL Server 2005 veraltet ist. (Die IMPLICIT INNER JOINin der Frage verwendete Syntax wird weiterhin unterstützt.)

Verfall der "Old Style" JOIN-Syntax: Nur eine teilweise Sache

Lomaxx
quelle
4
@lomaxx, können Sie aus Gründen der Klarheit angeben, welche Syntax der 2 in der Frage veraltet ist?
J Wynia
8
Können Sie unterstützende Unterlagen bereitstellen? Das klingt auf mehreren Ebenen falsch.
NotMe
21
Wie veraltet man den SQL-Standard?
David Crawshaw
7
@ David Crenshaw, der implizite Join ist nicht mehr im Standard und seit 18 Jahren nicht mehr.
HLGEM
11
Sogenannte "implizite Verknüpfungen" der Sorte "inner" oder "cross" verbleiben im Standard. SQL Server veraltet die Outer-Join-Syntax (dh *=und =*) im "alten Stil", die noch nie Standard war.
Tag, wenn
129

Persönlich bevorzuge ich die Join-Syntax, da dadurch klarer wird, dass die Tabellen verbunden sind und wie sie verbunden werden. Versuchen Sie, größere SQL-Abfragen zu vergleichen, bei denen Sie aus 8 verschiedenen Tabellen auswählen und im Wo viel gefiltert haben. Mithilfe der Verknüpfungssyntax trennen Sie die Teile, in denen die Tabellen verknüpft sind, von dem Teil, in dem Sie die Zeilen filtern.

grom
quelle
4
Ich stimme vollkommen zu, aber das ist eine Art Off-Topic. OP fragte nach Effizienz.
Villasv
56

Unter MySQL 5.1.51 haben beide Abfragen identische Ausführungspläne:

mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.02 sec)

mysql> explain select * from table1 a, table2 b where a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.00 sec)

table1hat 166208 Zeilen; table2hat ungefähr 1000 Zeilen.

Dies ist ein sehr einfacher Fall; Es beweist keineswegs, dass das Abfrageoptimierungsprogramm nicht verwirrt wird und in einem komplizierteren Fall unterschiedliche Pläne generiert.

Matt Fenwick
quelle
Dies sollte die akzeptierte Antwort sein. Dies ist richtig, der Plan ist derselbe (oder nahe an größeren Aussagen), aber die Anzahl der Datensätze wird drastisch sein, was zu Leistungsunterschieden führt.
SovietFrontier
37

Die zweite Syntax bietet die unerwünschte Möglichkeit eines Cross-Joins: Sie können dem FROM-Teil Tabellen hinzufügen, ohne die entsprechende WHERE-Klausel zu verwenden. Dies wird als schädlich angesehen.

edosoft
quelle
Was ist, wenn die Tabellennamen in der from-Klausel aus den in der where-Klausel verwendeten Tabellen generiert werden?
Jus12
Sie können auch einen Cross-Join mit der expliziten JOIN-Syntax durchführen ( stackoverflow.com/a/44438026/929164 ). Sie haben wahrscheinlich gemeint, dass dieser weniger streng und daher anfälliger für Benutzerfehler ist.
Daniel Dubovski
15

Die erste Antwort, die Sie gegeben haben, verwendet die sogenannte ANSI-Join-Syntax, die andere ist gültig und funktioniert in jeder relationalen Datenbank.

Ich stimme grom zu, dass Sie die ANSI-Join-Syntax verwenden sollten. Wie gesagt, der Hauptgrund ist die Klarheit. Anstatt eine where-Klausel mit vielen Prädikaten zu haben, von denen einige Verknüpfungstabellen und andere die mit der ANSI-Verknüpfungssyntax zurückgegebenen Zeilen einschränken, machen Sie blind klar, welche Bedingungen zum Verknüpfen Ihrer Tabellen verwendet werden und welche zum Einschränken der Ergebnisse.

andy47
quelle
5

In Bezug auf die Leistung sind sie genau gleich (zumindest in SQL Server). Beachten Sie jedoch, dass diese Join-Syntax nicht mehr unterstützt wird und von SQL Server 2005 nicht sofort unterstützt wird.

Ich denke, Sie denken an die veralteten Operatoren * = und = * im Vergleich zu "Outer Join".

Ich habe gerade die beiden angegebenen Formate getestet und sie funktionieren ordnungsgemäß in einer SQL Server 2008-Datenbank. In meinem Fall ergaben sie identische Ausführungspläne, aber ich konnte nicht sicher sagen, dass dies immer wahr sein würde.

Joshdan
quelle
5

@lomaxx: Zur Verdeutlichung bin ich mir ziemlich sicher, dass beide oben genannten Syntaxen von SQL Serv 2005 unterstützt werden. Die folgende Syntax wird jedoch NICHT unterstützt

select a.*, b.*  
from table a, table b  
where a.id *= b.id;

Insbesondere wird der äußere Join (* =) nicht unterstützt.

Deadbug
quelle
2
Ehrlich gesagt würde ich es nicht einmal in SQL Server 2000 verwenden, die Syntax * = gibt oft falsche Antworten. Manchmal werden diese als Cross-Joins interpretiert.
HLGEM
2

Bei einigen Datenbanken (insbesondere Oracle) kann die Reihenfolge der Verknüpfungen einen großen Unterschied für die Abfrageleistung bedeuten (wenn mehr als zwei Tabellen vorhanden sind). Bei einer Anwendung hatten wir in einigen Fällen buchstäblich zwei Größenordnungen Unterschied. Durch die Verwendung der inneren Join-Syntax können Sie dies steuern - wenn Sie die richtige Hinweissyntax verwenden.

Sie haben nicht angegeben, welche Datenbank Sie verwenden, aber die Wahrscheinlichkeit schlägt SQL Server oder MySQL vor, wo es keinen wirklichen Unterschied macht.

Leigh Caldwell
quelle
1
Leigh, Sie können die Hinweise auch in impliziten Verknüpfungen verwenden.
SquareCog
1
In Oracle ist es äußerst selten, dass die Verknüpfungsreihenfolge den Ausführungsplan auf sinnvolle Weise beeinflusst. Eine Erklärung finden Sie in diesem Artikel von Jonathan Lewis.
Jon Heller
1

Wie Leigh Caldwell festgestellt hat, kann das Abfrageoptimierungsprogramm verschiedene Abfragepläne erstellen, die darauf basieren, wie dieselbe SQL-Anweisung funktional aussieht. Weitere Informationen hierzu finden Sie in den folgenden beiden Blogeinträgen: -

Ein Beitrag des Oracle Optimizer-Teams

Ein weiterer Beitrag aus dem Blog "Structured Data"

Ich hoffe du findest das interessant.

Mike McAllister
quelle
Mike, der Unterschied, über den sie sprechen, besteht darin, dass Sie sicherstellen müssen, dass Sie, wenn Sie einen expliziten Join angeben, die Join-Bedingung angeben, für die Sie beitreten möchten, nicht den Filter. Sie werden feststellen, dass für semantisch korrekte Abfragen der Ausführungsplan derselbe ist.
SquareCog
1

In Bezug auf die Leistung sollte es keinen Unterschied machen. Die explizite Join-Syntax erscheint mir sauberer, da sie die Beziehungen zwischen Tabellen in der from-Klausel klar definiert und die where-Klausel nicht überladen.

David
quelle
0

Grundsätzlich besteht der Unterschied zwischen den beiden darin, dass einer auf die alte Art und Weise geschrieben ist, während der andere auf die moderne Art und Weise geschrieben ist. Persönlich bevorzuge ich das moderne Skript mit den inneren, linken, äußeren und rechten Definitionen, da diese erklärender sind und den Code besser lesbar machen.

Wenn es um innere Verknüpfungen geht, gibt es auch keinen wirklichen Unterschied in der Lesbarkeit. Es kann jedoch kompliziert werden, wenn Sie sich mit linken und rechten Verknüpfungen befassen, da Sie bei der älteren Methode ungefähr Folgendes erhalten würden:

SELECT * 
FROM table a, table b
WHERE a.id = b.id (+);

Das Obige ist die alte Art und Weise, wie eine linke Verknüpfung geschrieben wird, im Gegensatz zu der folgenden:

SELECT * 
FROM table a 
LEFT JOIN table b ON a.id = b.id;

Wie Sie visuell sehen können, macht die moderne Art und Weise, wie das Skript geschrieben wird, die Abfrage besser lesbar. (Übrigens gilt das Gleiche für rechte Verknüpfungen und etwas komplizierter für äußere Verknüpfungen).

Zurück zur Kesselplatte: Für den SQL-Compiler spielt es keine Rolle, wie die Abfrage geschrieben wird, da sie auf die gleiche Weise behandelt wird. Ich habe eine Mischung aus beidem in Oracle-Datenbanken gesehen, in die viele ältere und jüngere Leute geschrieben haben. Auch hier kommt es darauf an, wie lesbar das Skript ist und mit welchem ​​Team Sie sich entwickeln.

Michele La Ferla
quelle
-1

Nach meiner Erfahrung führt die Verwendung der Cross-Join-with-a-where-Klausel-Syntax häufig zu einem gehirngeschädigten Ausführungsplan, insbesondere wenn Sie ein Microsoft SQL-Produkt verwenden. Die Art und Weise, wie SQL Server beispielsweise versucht, die Anzahl der Tabellenzeilen zu schätzen, ist schrecklich. Durch die Verwendung der inneren Join-Syntax können Sie steuern, wie die Abfrage ausgeführt wird. Aus praktischer Sicht muss man sich angesichts des atavistischen Charakters der aktuellen Datenbanktechnologie für den inneren Join entscheiden.

Sean
quelle
5
Haben Sie einen Beweis dafür? Weil die akzeptierte Antwort etwas anderes sagt.
Cimmanon