Einzelnen Beitrag anzeigen

nahpets
(Gast)

n/a Beiträge
 
#3

AW: Index wird nicht imme rbenutzt

  Alt 4. Dez 2016, 16:20
Da stelle ich mal ein paar Vermutungen an:

Tabelle1 enthält viele Daten.
Tabelle2 enthält wenige Daten.

Die wenigen Daten aus Tabelle2 werden durch die Where-Bedingung noch starkt eingeschränkt.

Im Statement 1 wird für alle (also viele) Sätze aus Tabelle1 nachgeschaut, ob es in Tabelle2 was passendes gibt.

Im Statement 2 wird für wenige Sätze aus Tabelle2 nachgeschaut, ob es was in Tabelle1 gibt.

Die zu verarbeitenden Datenmengen unterscheiden sich hier also (vermutlich) sehr stark, auch wenn die Ergebnisse letztlich übereinstimmen.

Alternative:
SQL-Code:
select * from Tabelle1
where exists
(
  select 1
  from Tabelle2
  where Tabelle2.Auftrag = '66
  and Tabelle1.Ref = Tabelle2.Ref
)
Wobei mir nicht klar ist, wieso ein Left Outer Join, wenn nur Daten aus Tabelle1 benötigt werden?

Flapsig formuliert heißt das doch:

Nimm alles aus Tabelle1 und lege die Gegenstücke von Tabelle2 daneben, egal ob es sie gibt oder nicht, sofern der Auftrag in Tabelle2 gleich 66 ist und zeige mir die Daten aus Tabelle1.

Sinnvoller wäre aber doch:
Nimm alles aus Tabelle2, bei dem Auftrag gleich 66 ist, lege die Gegenstücke aus Tabelle1 daneben und zeige mir die Daten aus Tabelle1.

Übertrage das einfach mal auf Kästen mit Karteikarten und mache das händisch.

Vermutlich wirst Du die 2. Variante wählen, da hier die Vermutung nahe liegt, dass es mit weniger Aufwand zu erledigen sein wird.

Und für die Datenbank scheint es ebenso zu sein.

Wobei mir hier ein Left Outer Join unsinnig erscheint.

Wenn wir alles von Tabelle1 haben wollen und ggfls. alles aus der Tabelle2 daneben legen, sofern es denn existiert, wäre dies nur sinnvoll, wenn es in Tabelle2 keine weitere Einschränkung gibt.
Da hier aber auf Auftrag gleich 66 eingeschränkt wird, muss es ja was in Tabelle2 geben, damit ist der Left absolut überflüssig und ggfls. kontraproduktiv.

Bei mir sähe diese Abfrage ganz altbacken so aus:
SQL-Code:
select Tabelle1.* from Tabelle1, Tabelle2
where Tabelle1.Ref = Tabelle2.Ref
and Tabelle2.Auftrag = '66'
(Nach Oracleerfahrung: Rechts steht die Tabelle, die für die stärkste Einschränkung der Datenmenge sorgt. Keine Ahnung, ob Firebird da ggfls. ähnlich vorgeht.)

Du hast der Datenbank gegenüber aber den "Wissensvorsprung", dass Du weißt, welcher Weg der (vermutlich) einfachere sein wird.

Daher empfiehlt es sich immer, die Abfragen entsprechend aufzubauen.

Gerade bei großen Datenmengen kann man hierdurch schon mal sehr viel Laufzeit (und Arbeitsspeicher / temporär von der Datenbank genutzten Plattenspeicher) einsparen.

Meine praktische Erfahrung aus ein paar Jahrzehnten:

Baue eine Abfrage immer so auf, dass die von der Datenbank zu verarbeitende Datenmenge von vorneherein möglichst gering gehalten wird.
(Auch auf die Gefahr hin, dass eine Abfrage für den Menschen etwas schwieriger lesbar / verstehbar wird. Da helfen dann fundierte Kommentare.)

Geändert von nahpets ( 5. Dez 2016 um 14:49 Uhr) Grund: Schreibfehler behoben.
  Mit Zitat antworten Zitat