Inner Join vs Where

257

Gibt es einen Leistungsunterschied (im Orakel) zwischen

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

Und

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?

Juan
quelle
1
Nur zur
Veranschaulichung
12
@BlackTigerX: Unterschiedliche Ergebnisse? Gab es irgendwelche äußeren Verbindungen? Weil ich nicht sehe, wie unterschiedliche Ergebnisse zwischen einem inner join ... onund dem Einfügen gleichwertiger Verknüpfungskriterien in die whereKlausel auftreten würden.
Shannon Severance
in alter Version der Orakel-Datenbank nicht vorhandenjoin
MajidTaheri
2
@MajidTaheri: Wie alt ist eine Version von Oracle, von der Sie sprechen? Jede von Oracle unterstützte Version unterstützt die JOIN-Notation.
Jonathan Leffler
Achten Sie auf allgemeine Antworten oder Best Practices, die auf trivialen Fällen basieren. Ich würde gerne ein "Re-Match" mit komplexeren Klauseln sehen, die mehrere UND-Bedingungen beinhalten. Zumindest bei SQL Server gibt es einen Crossover-Punkt.
Crokusek

Antworten:

195

Nein! Schauen Sie sich diese beiden Tabellen an, um denselben Ausführungsplan zu erstellen:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

Der Ausführungsplan für die Abfrage mit dem inneren Join:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

Und der Ausführungsplan für die Abfrage unter Verwendung einer WHERE-Klausel.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2
kiewic
quelle
4
Ich möchte wirklich sehen, ob es eine offizielle Dokumentation von Oracle gibt, die dies sagt
4 Leave Cover
68

Wenn der Abfrageoptimierer seine Arbeit richtig macht, sollte es keinen Unterschied zwischen diesen Abfragen geben. Sie sind nur zwei Möglichkeiten, um das gleiche gewünschte Ergebnis anzugeben.

Craig Trader
quelle
22
Ja, die Leistung sollte gleich sein. Aber die Syntax SELECT * FROM Table1, Table2 WHERE ... ist EVIL!
Joel Coehoorn
2
Ich finde es viel einfacher, FOR INNER JOINS zu verstehen als die SQL-92-Syntax. Ihr Kilometerstand kann variieren.
Craig Trader
25
Ich finde die WHERE-Syntax leichter zu lesen als INNER JION - ich denke, es ist wie Vegemite. Die meisten Menschen auf der Welt finden es wahrscheinlich ekelhaft, aber Kinder, die es essen, lieben es.
ScottCher
3
Vegemite ist in der Tat böse, aber andererseits liebe ich Scrapple. Stelle dir das vor.
StingyJack
2
@Darryl Ich denke, die JOINs sind leichter zu lesen, da die Bedingung für das Verbinden der Tabellen sofort dort definiert wird, anstatt "irgendwo" in der WHEREKlausel. Ich ziehe es vor, die WHEREKlausel zur Begrenzung des Datensatzes (z. B. WHERE DATE > (SYSDATE - 1)) zu reservieren, anstatt auch zu definieren, wie sich die Tabellen zueinander verhalten (z WHERE T1.ID = T2.ID. B. ). Für eine kleine Tabelle wie das fragliche Beispiel macht das wenig Unterschied, aber für große Abfragen mit mehreren Tabellen und mehreren Bedingungen ist die Abfrage meiner Meinung nach viel einfacher zu verstehen.
ImaginaryHuman072889
61

Sie sollten genau gleich sein. Als Codierungspraxis würde ich jedoch lieber den Join sehen. Es artikuliert klar Ihre Absicht,

Nescio
quelle
8
Genau. Insbesondere wenn Sie mehreren Tabellen beitreten, ist es viel einfacher, eine select-Anweisung zu analysieren, wenn Sie explizite Verknüpfungen ausführen.
Paul Morie
13
Tatsächlich. Verknüpfungen stellen eine semantische Beziehung zwischen zwei Datensätzen dar, aber ein Where schlägt einen gefilterten Satz vor. +1
EightyOne Unite
26

Die Verwendung JOINerleichtert das Lesen des Codes, da er selbsterklärend ist.

Es gibt keinen Unterschied in der Geschwindigkeit ( ich habe es gerade getestet ) und der Ausführungsplan ist der gleiche.

user21241
quelle
Danke dir. Ich suchte nach Geschwindigkeitskomprimierung zwischen diesen beiden Methoden.
Farhad Navayazdan
14

Ich weiß nichts über Oracle, aber ich weiß, dass die alte Syntax in SQL Server veraltet ist und irgendwann verschwinden wird. Bevor ich diese alte Syntax in einer neuen Abfrage verwendete, überprüfte ich, was Oracle damit vorhat.

Ich bevorzuge die neuere Syntax gegenüber dem Mischen der Verknüpfungskriterien mit anderen erforderlichen Bedingungen. In der neueren Syntax ist viel klarer, was den Join erstellt und welche anderen Bedingungen angewendet werden. Nicht wirklich ein großes Problem bei einer kurzen Abfrage wie dieser, aber es wird viel verwirrender, wenn Sie eine komplexere Abfrage haben. Da die Benutzer die grundlegenden Abfragen kennen, würde ich es vorziehen, wenn die Benutzer lernen, die Join-Syntax zu verwenden, bevor sie sie in einer komplexen Abfrage benötigen.

Auch hier kenne ich Oracle nicht speziell, aber ich weiß, dass die SQL Server-Version des Links-Joins im alten Stil selbst in SQL Server 2000 fehlerhaft ist und inkonsistente Ergebnisse liefert (manchmal ein Links-Join, manchmal ein Cross-Join), daher sollte dies niemals der Fall sein gebraucht. Hoffentlich hat Oracle nicht das gleiche Problem, aber sicherlich können Links- und Rechtsverknüpfungen in der alten Syntax schwieriger auszudrücken sein.

Außerdem habe ich die Erfahrung gemacht (und dies ist natürlich eine rein persönliche Meinung, Sie haben möglicherweise andere Erfahrungen), dass Entwickler, die die ANSII-Standard-Joins verwenden, tendenziell besser verstehen, was ein Join ist und was es für das Erhalten bedeutet Daten aus der Datenbank. Ich glaube, das liegt daran, dass die meisten Leute mit gutem Datenbankverständnis dazu neigen, komplexere Abfragen zu schreiben, und diese scheinen mir mit dem ANSII-Standard viel einfacher zu pflegen zu sein als mit dem alten Stil.

HLGEM
quelle
1
Amen Bruder. Nieder mit den JOINERS !!
ScottCher
14

[Für einen Bonuspunkt ...]

Mit der JOIN-Syntax können Sie den Join einfacher auskommentieren, da alles in einer Zeile enthalten ist. Dies kann nützlich sein, wenn Sie eine komplexe Abfrage debuggen

Wie alle anderen sagen, sind sie funktional gleich, jedoch ist der JOIN klarer von einer Absichtserklärung. Es kann daher dem Abfrageoptimierer in bestimmten Fällen entweder in aktuellen Oracle-Versionen helfen (ich habe keine Ahnung, ob dies der Fall ist), es kann dem Abfrageoptimierer in zukünftigen Versionen von Oracle helfen (niemand hat eine Idee) oder es kann helfen, wenn Sie wechseln den Datenbanklieferanten.

Chris Gill
quelle
2
Oder ... ändern Sie einfach die INNER JOINS in LEFT JOINS, damit Sie sehen, bei welchem ​​Join Sie die erwarteten Zeilen verpassen. Ich mache das, weil ich die ganze Abfrage auf einmal mache. Wenn Sie INNER JOINS auskommentieren, müssen Sie eine Art Eliminierungsprozess durchführen. Es dauert länger. Aber +1 für Sie, denn dies ist neben der Lesbarkeit einer meiner Lieblingsgründe für INNER JOINS!
Matthew McPeak
13

Sie sind logisch identisch, aber in früheren Versionen von Oracle, in denen die ANSI-Syntax verwendet wurde, traten in komplexeren Fällen häufig Fehler auf, sodass Oracle-Entwickler bei der Verwendung manchmal auf Widerstand stoßen.

David Aldridge
quelle
Frühere Versionen von Oracle hatten Fehler damit? Wie früh? Welche Version (en)?
ScottCher
Metalink hat Details ... sie tauchen überall auf.
David Aldridge
7

Die Leistung sollte identisch sein, aber ich würde empfehlen, die Join-Version zu verwenden, da die Klarheit bei äußeren Joins verbessert wird.

Auch unbeabsichtigte kartesische Produkte können mit der Join-Version vermieden werden.

Ein dritter Effekt ist eine leichter zu lesende SQL mit einer einfacheren WHERE-Bedingung.

stili
quelle
Ich denke wirklich, dass der Schlüssel unbeabsichtigte Effekte sind, bei denen die Kriterien nicht eindeutig sind. Wenn Sie den Join-Typ angeben, wissen Sie genau, was Sie erhalten. Ich habe festgestellt, dass verschiedene Datenbanken und sogar verschiedene Versionen derselben Datenbankplattform Nullwerte in einem impliziten Join unterschiedlich behandeln. Wenn Sie links / rechts innen / außen angeben, verbringen Sie die Zeit damit, darüber nachzudenken, was richtig ist. Wenn Sie die mehrdeutige Methode verwenden, gehen Sie davon aus, dass sie so funktioniert, wie Sie es sich erhoffen / beabsichtigen.
Steve Kallestad
6

Vergessen Sie nicht, dass Sie in Oracle, sofern die Join-Schlüsselattribute in beiden Tabellen gleich benannt sind, dies auch wie folgt schreiben können:

select *
from Table1 inner join Table2 using (ID);

Dies hat natürlich auch den gleichen Abfrageplan.

Cheduardo
quelle
Ich habe die Ausgabe zurückgesetzt, weil die vorherige Überarbeitung die Bedeutung der Antwort geändert hat
Juan
5

In einem Szenario, in dem Tabellen in der 3. Normalform vorliegen, sollten sich Verknüpfungen zwischen Tabellen nicht ändern. Dh KUNDEN beitreten und ZAHLUNGEN sollten immer gleich bleiben.

Wir sollten jedoch Verknüpfungen von Filtern unterscheiden . Bei Verknüpfungen geht es um Beziehungen, und bei Filtern geht es um die Partitionierung eines Ganzen.

Einige Autoren, die sich auf den Standard beziehen (z. B. Jim Melton; Alan R. Simon (1993). Verständnis des neuen SQL: Ein vollständiger Leitfaden. Morgan Kaufmann. S. 11–12. ISBN 978-1-55860-245-8.) , schrieb über die Vorteile der Übernahme der JOIN-Syntax gegenüber durch Kommas getrennten Tabellen in der FROM-Klausel.

Ich stimme diesem Standpunkt voll und ganz zu.

Es gibt verschiedene Möglichkeiten, SQL zu schreiben und die gleichen Ergebnisse zu erzielen. Für viele Teammitglieder ist jedoch die Lesbarkeit des Quellcodes ein wichtiger Aspekt. Die Trennung der Tabellen von bestimmten Filtern war sicherlich ein großer Schritt, um die Quelle zu klären Code.

abrittaf
quelle
Inner Join on bedeutet Cross Join wo. Komma ist Cross-Join mit niedrigerer Priorität als Keyword-Joins. On vs "Filter" ist für die innere Verknüpfung irrelevant. NFs sind für die Abfrage irrelevant. Nichts im Standard fördert Keyword-Verknüpfungen über Komma. Triviale Optimierungen behandeln & wo gleich. Diese Antwort ist eine Reihe von Missverständnissen.
philipxy
1) Ich denke, @philipxy versucht zu sagen: "In FROM-Klauseln haben durch Komma getrennte Tabellen dieselbe Bedeutung wie Tabellen CROSS JOINed." Ich stimme dem zu. Natürlich können Sie sich an die alte Syntax halten und diese kann mit JOIN-Klauseln koexistieren. RDBMS-Optimierer werden beide Fälle perfekt als gleich verstehen (falls sie natürlich gleichwertig sind) und denselben Plan ausarbeiten.
Abrittaf
4

In PostgreSQL gibt es definitiv keinen Unterschied - beide entsprechen demselben Abfrageplan. Ich bin mir zu 99% sicher, dass dies auch bei Oracle der Fall ist.

Nick Johnson
quelle
2

Sie sind beide innere Verknüpfungen, die dasselbe tun. Man verwendet einfach die neuere ANSI-Syntax.

Bob Gettys
quelle
2

Funktionell sind sie die gleichen wie gesagt. Ich stimme jedoch zu, dass der Join besser ist, um genau zu beschreiben, was Sie tun möchten. Oft dachte ich, ich wüsste, wie ich etwas abfragen wollte, bis ich anfing, die Verknüpfungen durchzuführen, und mir wurde klar, dass ich eine andere Abfrage als die ursprüngliche in meinem Kopf durchführen wollte.

MattC
quelle
1

Es ist richtig, dass funktional beide Abfragen auf die gleiche Weise verarbeitet werden sollten. Die Erfahrung hat jedoch gezeigt, dass es bei der Auswahl aus Ansichten, die die neue Join-Syntax verwenden, wichtig ist, Ihre Abfragen auch damit zu strukturieren. Das Optimierungsprogramm von Oracle kann verwirrt werden, wenn eine Ansicht eine "join" -Anweisung verwendet, eine Abfrage, die auf die Ansicht zugreift, jedoch die herkömmliche Methode zum Verknüpfen der "where" -Klausel verwendet.

JoshL
quelle
Das ist eher ein Problem mit Ansichten als mit Verknüpfungen.
vorhanden
0

Obwohl die Identität von zwei Abfragen offensichtlich erscheint, passieren manchmal einige seltsame Dinge. Ich bin auf die Abfrage gestoßen, die unterschiedliche Ausführungspläne hat, wenn das Join-Prädikat in Oracle 10g von JOIN nach WHERE verschoben wird (denn der WHERE-Plan ist besser), aber ich kann dieses Problem nicht in vereinfachten Tabellen und Daten reproduzieren. Ich denke, das hängt von meinen Daten und Statistiken ab. Optimizer ist ein ziemlich komplexes Modul und verhält sich manchmal magisch.

Deshalb können wir diese Frage im Allgemeinen nicht beantworten, da sie von DB-Interna abhängt. Aber wir sollten wissen, dass die Antwort " keine Unterschiede " sein muss.

Greatvovan
quelle
0

Ich hatte dieses Rätsel heute, als ich eines der Zeitlimits unserer SP in der Produktion untersuchte und stattdessen einen inneren Join in einer Tabelle, der aus einem XML-Feed erstellt wurde, in eine 'where'-Klausel änderte. Die durchschnittliche Ausführungszeit beträgt jetzt 80 ms über 1000 Ausführungen bevor die durchschnittliche Ausführung 2,2 Sekunden betrug ... Hauptunterschied im Ausführungsplan ist das Verschwinden einer Schlüsselsuche ... Die Nachricht, die Sie erst kennen, wenn Sie beide Methoden getestet haben.

Prost.

trbullet81
quelle
0

Wie Kiewik sagte, ist der Ausführungsplan der gleiche.

Die JOIN-Anweisung ist nur einfacher zu lesen, wodurch es einfacher wird, den EIN-Zustand nicht zu vergessen und ein kartesisches Produkt zu erhalten. Diese Fehler können bei langen Abfragen mit mehreren Verknüpfungen des Typs sehr schwer zu erkennen sein: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Wenn Sie nur eine Join-Bedingung vergessen, haben Sie eine sehr lange Zeit, um eine Abfrage auszuführen, die zu viele Datensätze zurückgibt ... wirklich zu viele. Einige Leute verwenden ein DISTINCT, um die Abfrage zu patchen, aber die Ausführung dauert noch sehr lange.

Genau aus diesem Grund ist die Verwendung der JOIN-Anweisung sicherlich die beste Vorgehensweise: eine bessere Wartbarkeit und eine bessere Lesbarkeit.

Wenn ich mich recht erinnere, ist JOIN außerdem hinsichtlich der Speichernutzung optimiert.

ROQUEFORT François
quelle
0

Ich habe eine Ergänzung zu dieser guten Antwort :

Das ist, was als SQL92 bzw. SQL89 definiert ist, es gibt keinen Leistungsunterschied zwischen ihnen, obwohl Sie das Wort INNER weglassen können (nur JOIN zu verwenden ist klar genug und in der einfachsten Abfrage speichern Sie 5 Tastaturanschläge. Stellen Sie sich jetzt vor, wie viele Anschläge es in großen gibt Einsen).

Ivanzinho
quelle