2010-01-21 6 views
5

Ich finde mich oft wollen eine SQL-Abfrage wie folgt schreiben:SQL: Ist eine Abfrage wie diese OK oder gibt es einen effizienteren Weg, wie eine Verbindung zu verwenden?

SELECT body 
    FROM node_revisions 
where vid = (SELECT vid 
       FROM node 
       WHERE nid = 4); 

Ich weiß, dass es schließt sich und Dinge, die Sie tun können, aber sie scheinen die Dinge komplizierter zu machen. Sind Joins ein besserer Weg dies zu tun? Ist es effizienter? Leichter zu verstehen?

+1

Ich würde wetten, dass diese Abfrage und der logisch gleichwertige Join auf SQL Server identische Abfrageausführungspläne haben würden. – Dana

Antwort

7

tritt effizienter neigen, da Datenbanken mit Set-Operationen im Kopf geschrieben werden (und Operationen sind so eingestellt Joins).

Die Leistung variiert jedoch von Datenbank zu Datenbank, wie die Tabellen strukturiert sind, wie viel Daten in ihnen enthalten sind und wie viel von der Abfrage zurückgegeben wird.

Wenn die Datenmenge klein ist, würde ich eine Unterabfrage wie Ihre statt einer Verknüpfung verwenden.

Hier ist, was ein aussehen würde beitreten:

SELECT body 
FROM node_revisions nr 
INNER JOIN node n 
    ON nr.vid = n.vid 
WHERE n.nid = 4 

würde ich nicht die Abfrage verwenden Sie auf dem Laufenden, wie es zufällig von mehr als einem Knotendatensatz mit einem nid = 4 ist, die es verursachen würde scheitern.

Ich würde verwenden:

SELECT body 
FROM node_revisions 
WHERE vid IN (SELECT vid 
      FROM node 
      WHERE nid = 4); 

Ist dies besser lesbar oder verständlich? In diesem Fall ist es eine Frage der persönlichen Präferenz.

+0

Es ist viel mehr als persönliche Vorliebe. Ich würde gerne einen Join auf zwei Spalten mit IN sehen, die in der Lesbarkeit vergleicht. Ehrlich gesagt, kann die Übernutzung von IN für mich ein Symptom eines konzeptionellen Kernproblems in SQL sein. – ErikE

1
select 
    body 
from node_revisions A 
where exists (select 'x' 
       from Node B 
       Where A.Vid = B.Vid and B.NID=4) 
+2

Warum ist das besser? Es scheint komplizierter. –

+0

Es ist komplizierter, aber es macht auch nicht das Gleiche. Dies ist ein Semi-Join, der dem Datenbankserver in einigen Fällen eine Optimierung ermöglicht. Es gibt auch immer nur eine Zeile aus der Haupttabelle zurück, egal wie viele übereinstimmende Zeilen in der Unterabfragetabelle gefunden werden. Beachten Sie, dass Sie in der Hauptabfrage nicht auf Spalten in der Unterabfrage verweisen können, aber das ist der Punkt: Sie suchen nach * existence *, ziehen keine Daten.Wenn die Unterabfragetabelle VIELE Zeilen pro Zeile in der äußeren Tabelle hat, kann die Syntax von exists weit effizienter sein, da sie nach dem Auffinden von nur einer Datei anhalten kann. – ErikE

+0

Dies entspricht nicht der ursprünglichen Abfrage. Wenn die Unterabfrage mehrere Zeilen zurückgibt, funktioniert dies und die ursprüngliche Abfrage schlägt fehl. Dies wäre äquivalent zu einer Abfrage mit 'IN' anstelle von' = '. Alle modernen Engines können jedoch sowohl "EXISTS" als auch "IN" für einen Semi-Join optimieren. – Quassnoi

3

die Antwort auf eine leistungsbezogene Fragen in Datenbanken ist es abhängig ist, und wir sind auf Details im OP kurz. keine Einzelheiten über Ihre Situation zu wissen, ... (so sind diese allgemeine Faustregeln)

schließt sich besser und leichter

  • aus irgendeinem Grund mehrere Spaltenschlüssel (fischig) benötigen Wenn zu verstehen , können Sie weiterhin einen Join verwenden und einfach einen anderen Ausdruck auf die Join-Bedingung anwenden.
  • Wenn Sie in Zukunft wirklich zusätzliche Daten hinzufügen müssen, ist das Join-Framework bereits vorhanden.
  • Es macht es klarer, was genau Sie verbinden und wo Indizes implementiert werden sollten.
  • Die Verwendung von Joins verbessert die Joins und verbessert das Nachdenken über Joins.
  • schließt sich klar darüber, welche Tabellen im Spiel sind

Schriftliche Anfragen nichts mit effiency zu tun haben *

Die Abfragen, die Sie schreiben und was wird tatsächlich laufen wenig miteinander zu tun. Es gibt viele Möglichkeiten, eine Abfrage zu schreiben, aber nur so wenige Möglichkeiten, die Daten abzurufen, und die Abfrage-Engine entscheidet selbst. Dies betrifft hauptsächlich Indizes. Es ist sehr gut möglich, vier Abfragen zu schreiben, die völlig anders aussehen, aber intern dasselbe tun.

(* Es ist möglich, eine schreckliche Abfrage zu schreiben, die ineffizient ist, aber es dauert eine besondere Art von verrückt, das zu tun.)

select 
    body 

from node_revisions nr 

join node n 
on n.vid = nr.vid 

where n.nid = 4 
1

Der neueste Code MySQL 6.x automatisch, dass konvertiert IN Ausdruck in ein INNER JOIN eine Semi-Join-Unterabfrage-Optimierung, so dass die 2-Anweisungen weitgehend gleichwertig:

http://forge.mysql.com/worklog/task.php?id=3740

aber, eigentlich ist es heraus zu schreiben ist ziemlich einfach zu tun, weil INNER JOIN der Standard-Join-Typ ist, und dies würde nicht davon abhängen, dass der Server es optimiert (was es aus irgendeinem Grund nicht tun würde und welches nicht notwendigerweise portierbar wäre). alle Dinge gleich sind, warum nicht mit:

select body from node_revisions r, node n where r.vid = n.vid and n.node = 4 
3

Ich denke Joins sind leichter zu verstehen und effizienter sein. Ihr Fall ist ziemlich einfach, also ist es wahrscheinlich ein Toss-Up. Hier ist, wie ich es schreiben würde:

SELECT body 
    FROM node_revisions 
    inner join node 
     on (node_revisions.vid = node.vid) 
    WHERE node.nid = 4 
1

Ich sehe nichts falsch mit dem, was Sie geschrieben haben, und ein guter Optimierer kann es sogar zu einer Änderung kommen, wenn es für richtig hält.

1
SELECT body 
FROM node_revisions 
WHERE vid = 
     (
     SELECT vid 
     FROM node 
     WHERE nid = 4 
     ) 

Diese Abfrage ist logisch äquivalent zu einem Join, wenn und nur wenn nid ein PRIMARY KEY ist oder durch eine UNIQUE Einschränkung abgedeckt.

Andernfalls sind die Abfragen nicht gleichwertig: ein Join wird immer erfolgreich sein, während die Unterabfrage fehlschlägt, wenn mehr als 1 Zeile in node mit nid = 4 sind.

Wenn nid eine PRIMARY KEY ist, haben die JOIN und die Unterabfrage dieselbe Leistung.

Bei einer Verknüpfung wird node

Im Falle einer Unterabfrage führenden

gemacht werden, wird die Unterabfrage und einmal in eine const transformiert ausgeführt werden auf der Bühne Parsen.

+0

Yup, Nid und Vid sind eindeutige Primärschlüssel. –

+0

'@Brian T. Hannan': dann sind die Abfragen identisch. 'JOIN' und die Unterabfrage werden dasselbe ausführen. – Quassnoi

2

Ein Join ist interessant:

select body 
from node_revisions nr 
join node n on nr.vid = n.vid 
where n.vid = 4 

Sie können aber auch ein ohne Join Express [!]:

select body 
from node_revisions nr, node n 
where n.nid = 4 and nr.vid = n.vid 

Interessanterweise SQL Server einen geringfügigen unterschiedlichen Abfrage-Plan auf beide geben Abfragen, während der Join einen Clustered-Index-Scan hat, die "Join ohne Join" hat eine Clustered-Index-Suche an seiner Stelle, die es anzeigt, ist better, zumindest in diesem Fall!

Verwandte Themen