AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

SQL optimieren

Ein Thema von Dumpfbacke · begonnen am 23. Mai 2013 · letzter Beitrag vom 30. Mai 2013
Antwort Antwort
Seite 1 von 2  1 2   
Furtbichler
(Gast)

n/a Beiträge
 
#1

AW: SQL optimieren

  Alt 23. Mai 2013, 19:15
Hast Du auch einen kombinierten Index (Feld1, Feld2) in beiden Tabellen? Das sollte dann optimal sein, denke ich.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#2

AW: SQL optimieren

  Alt 23. Mai 2013, 19:29
Unique Index wäre vlt auch toll, wenn möglich.
Die unique - oder kombi - Indizierung könnte allerdings negative Auswirkungen auf andere Statements haben.
Mal den Ausführungsplan fragen.

Die Where Bedingung in Deinem Statement enthält wahrscheinlich ein Tipfehler oder (Feld2 ist Teil des Joins)?
Gruß, Jo
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#3

AW: SQL optimieren

  Alt 23. Mai 2013, 19:42
Die Where Bedingung in Deinem Statement enthält wahrscheinlich ein Tipfehler oder (Feld2 ist Teil des Joins)?
Nein, das ist korrekt. Was bring 'Unique' für einen Geschwindigkeitsvorteil?
  Mit Zitat antworten Zitat
jensw_2000
(Gast)

n/a Beiträge
 
#4

AW: SQL optimieren

  Alt 24. Mai 2013, 00:49
Ich denke es müsste schon mal etwas schneller gehen, wenn Du die "is NULL" Prüfung für Tabelle2.Feld2 mit als JOIN Bedingung setzt und Tabelle1.Feld2 in der Where Klausel auf NULL Werte prüfst.

Code:
Select
  Tabelle1.Feld1
from
  Tabelle1
Left Outer Join Tabelle2 
  on Tabelle2.Feld1 = Tabelle1.Feld1
  and Tabelle2.Feld2 is null
Where
  Tabelle1.Feld2 IS NULL

Der Ausführungsplan (ohne Indizes) sollte bei dieser Abfrage wie folgt aussehen:
1. Hole alle Datensätze aus Tabelle 1 bei denen Feld 2 einen NULL Wert enthält
2. Joine alle Datensätze aus Tabelle 2, in denen Feld 2 Null ist und Feld1 eine Entsprechung in der (im Schritt 1 reduzierten Datenmenge von) Tabelle1 hat.

Damit wird die "logische Datenmenge" während der Ausführung deutlich kleiner.
Indizes auf Tabelle1.Feld2, Tabelle2.Feld1 und Tabelle2.Feld2 sind aber dennoch wichtig.

Bei deiner originalen Abfrage muss der SQL Server wegen der "Tabelle2" Where Bedingung erst den inneren Teil abarbeiten, bevor das Where greifen kann. Im Join werden die NULL Werte in Tabelle2.Feld2 nicht als Bedingung gesetzt. Daher muss der SQL Server hier sehr viele Datensätze aus Tabelle2 "pauschal" mit Tabelle1 joinen um sie dann später wieder reduzieren zu können.

Geändert von jensw_2000 (24. Mai 2013 um 00:52 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#5

AW: SQL optimieren

  Alt 24. Mai 2013, 05:52
Du scheinst nicht verstanden zu haben, was der Fragesteller möchte und wie das mit dem 'WHERE X is null' funktioniert, auf jeden Fall sind deine Ausführungen falsch.

Also: Zwei Tabellen A und B, jeweils eine Spalte ID. A=(1,2,3) B=(2,3,4). select * from A left join B on A.ID=B.ID liefert:
Code:
A.ID B.ID
1    NULL
2    2
3    3
Warum? Der SELECT-Befehl lässt sich übersetzen mit: Alles aus A (LEFT JOIN) und falls B passt (ON A.ID=B.ID), auch von B.
Nun möchte er nur die '1' sehen, denn die ist in B nicht vorhanden: Also WHERE B.ID is NULL .
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#6

AW: SQL optimieren

  Alt 24. Mai 2013, 06:27
Korrekt, ich hab nicht richtig hingeschaut.
Ja und Unique könnte eine höhere Selektivität bringen bzw. den Optimizer dazu bringen den Ausführungsplan zu ändern.
Kein Range Index Scan halt, wie gesagt, der Ausführungsplan würde es verraten.
Gruß, Jo

Geändert von jobo (24. Mai 2013 um 06:29 Uhr)
  Mit Zitat antworten Zitat
jensw_2000
(Gast)

n/a Beiträge
 
#7

AW: SQL optimieren

  Alt 24. Mai 2013, 06:29
Ich denke du solltest dich ggf. mit den Basics von SQL Ausführungsplänen auseinandersetzen, bevor du anderen unterstellst, dass sie irgend etwas nicht verstanden haben.
Code:
WHERE B.ID is NULL
funktioniert. Ganz klar.
Allerdings ist es suboptimal, weil der SQL Server weder die innere noch die äußere Abfrage optimiert ausführen kann.
Wenn B.ID NULL sein soll, dann kann man dies um ein vielfaches effektiver als Condition für den Join festlegen.
Schau Dir mal SQL Profiling Tools an und vergleiche die Ausführungspläne beider Varianten.

PS:
Du scheinst nicht verstanden zu haben, was der Fragesteller möchte und wie das mit dem 'WHERE X is null' funktioniert, auf jeden Fall sind deine Ausführungen falsch.
Oh Sorry. Ich dachte das war auf mich gemünzt.

Geändert von jensw_2000 (24. Mai 2013 um 06:32 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#8

AW: SQL optimieren

  Alt 24. Mai 2013, 06:50
Jens, meine Antwort unter Deiner war mißverständlich, aber Du warst schon gemeint. Hach ich bin eben etwas ruppig, manchmal. Und kann nicht richtig lesen. Ich hab deine Ausführungen noch nicht einmal richtig gelesen, aber schon verteufelt.

Aber bei mir funktioniert dein Vorschlag nicht. Ich habe zwar nur einen SQL-Server (TM von MS), aber dieses Skript geht nicht:
SQL-Code:
--- Temporäre Tabellen anlegen
select 1 as ID1, 1 as ID2 into #A
union select 1,2
union select 1,3
union select 2,1
union select 2,2

select 1 as ID1, 1 as ID2 into #B
union select 1,2
union select 1,3
union select 2,1
union select 2,3

--- Vorschlag #1 (funktioniert)
select *
from #A a
     left join #B b
       on a.ID1=b.ID1
      and a.ID2=b.ID2
where b.ID2 is null

--- Vorschlag #2 (deiner?)
Select *
from #A a
  left join #B b
    on a.ID1=b.ID1
   and b.ID2 is null
where b.ID2 is null
Wenn man nicht weiter weiß (bei Performanceproblemen) hilft mir manchmal, einfach einen anderen ansatz zu nehmen.
Code:
select * from Tabelle1
where not exists (
  select * from Tabelle2 
   where Tabelle1.Feld1=Tabelle2.Feld1 
     and Tabelle1.Feld2=Tabelle2.Feld2
   )
Das kann zum identischen Queryplan führen, oder etwas komplett anderes bewirken. Wichtig hier scheint mir, einen kombinierten Index auf Tabelle2 (Feld1+Feld2) zu haben, oder?

Geändert von Furtbichler (24. Mai 2013 um 06:52 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#9

AW: SQL optimieren

  Alt 24. Mai 2013, 08:19
Hast Du auch einen kombinierten Index (Feld1, Feld2) in beiden Tabellen? Das sollte dann optimal sein, denke ich.
In Tabelle1 wird zumindest in dieser Abfrage überhaupt kein Index benötigt, es werden sowieso alle Datensätze berücksichtigt.

Nach meiner Erfahrung ist der kombinierte Index in Tabelle2 (Feld1, Feld2) die einzige sinnvolle Lösung.
Der Index, der nur Feld1 berücksichtigt, kann dann aber entfallen.

Wahrscheinlich müssen die Felder auch in der Join-Bedingung der Abfrage in der selben Reihenfolge wie im Index auftauchen.
Code:
  Select         Tabelle1.Feld1
  from           Tabelle1
  Left Outer Join Tabelle2 on Tabelle1.Feld1 = Tabelle2.Feld1
                          and Tabelle1.Feld2 = Tabelle2.Feld2
  where Tabelle2.Feld2 is null
Im Plan darf dann nur noch dieser kombinierte Index auftauchen.
  Mit Zitat antworten Zitat
tgvoelker

Registriert seit: 9. Sep 2002
Ort: Oelsnitz, Vogtland
44 Beiträge
 
Delphi 12 Athens
 
#10

AW: SQL optimieren

  Alt 26. Mai 2013, 19:19
EDIT: Furtbichler hat recht.

Code:
Select Tabelle1.Feld1
from Tabelle1
Left Outer Join Tabelle2 on Tabelle1.Feld2 = Tabelle2.Feld2
 and Tabelle1.Feld1 = Tabelle2.Feld1
where Tabelle2.Feld2 is null
Zitat:
Als Ergebnis möchte ich alle Felder1 der Tabelle1 bei denen es in der Tabelle2 nicht einen Datenstz gibt mit dem selben Daten in den Felder1 und 2 wie in der Tabelle 1.
Kombinierten Index machen in beiden Tabellen und das müßte es sein. Ggf. kannst Du auch einen referentiellen Constraint erstellen, könnte einen Zacken schneller sein.

Die Query kombiniert alle Tupel aus Tabelle 1 mit allen Tupeln aus Tabelle 2, bei denen die Kombination der Felder Feld1 und Feld2 in beiden Tabellen die gleichen Daten haben. Damit nun die WHERE-Klausel alle Tupel aus Tabelle 1 liefert, für die mit dieser Bildungsvorschrift kein Datensatz in Tabelle 2 zugeordnet werden kann, darf Tabelle2.Feld2 keine Nullwerte akzeptieren.

Jensw_2000:

Das hier:

Code:
Select
  Tabelle1.Feld1
from
  Tabelle1
Left Outer Join Tabelle2 
  on Tabelle2.Feld1 = Tabelle1.Feld1
  and Tabelle2.Feld2 is null
Where
  Tabelle1.Feld2 IS NULL
macht was anderes. Es kombiniert alle Tupel aus Tabelle 1 mit allen Tupeln aus Tabelle 2, für die Feld1 jeweils die gleichen Daten enthält und Feld2 in Tabelle 2 NULL ist. Die Where-Klausel filtert lediglich die Tupel aus Tabelle 1, für die Feld2 NULL ist.

Deine Bildungsvorschrift verletzt also die implizite Voraussetzung, daß Feld2 in Tabelle2 keine Nullwerte akzeptiert. Stattdessen gehst Du davon aus, daß Nullwerte zugelassen sind - denn mit Deiner WHERE-Klausel schmeißt Du ja alle Tupel aus Tabelle 1 weg, die in Feld2 keinen NULL stehen haben.

Genaugenommen wird die Ergebnismenge von Dir alle die Tupel aus Tabelle 1 enthalten, für die die Kombination Feld1/Feld2 in Tabelle 2 vorhanden ist und Tabelle1.Feld2 NULL ist.
Thomas Völker

Geändert von tgvoelker (26. Mai 2013 um 19:21 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz