select distinct sr.styleid, sr.gender, se.agemin * 1000 + se.agemax as agegroup
from swimresult sr
left join swimevent se on se.swimeventid = sr.swimeventid
left join swimresult sr2 on sr.gender=sr2.gender and sr.styleid=sr2.styleid and sr.course = sr2.course
left join recorditem ri on ri.swimresultid = sr2.swimresultid and ri.recordlistid = 50069
where sr.meetid = 627794 and sr.place = 1 and sr.styleid <= 20 and se.agemin >= 25 and ri.swimresultid is null
Ich weiss, ein left join ist immer langsam aber über den Filter sr.meetid = 62774 habe ich ein Kriterium das aus der Tabelle mit mehreren Millionen Datensätzen etwa 2000 Datensätze auswählt. Das Query läuft ewigs, nach 15 Minuten habe ich abgebrochen.
Was mache ich falsch?
Hast Du mal versucht die LEFT JOINs durch NOT EXIST Bedingungen zu ersetzen? Dann kannst Du vermutlich auch das DISTINCT weglassen:
select sr.styleid, sr.gender, se.agemin * 1000 + se.agemax as agegroup
from swimresult sr
left join swimevent se on se.swimeventid = sr.swimeventid
where sr.meetid = 627794
and sr.place = 1
and sr.styleid <= 20
and se.agemin >= 25
and not exists (select *
from recorditem ri
join swimresult sr2 on ri.swimresultid = sr2.swimresultid
where ri.recordlistid = 50069
and sr.gender = sr2.gender
and sr.styleid = sr2.styleid
and sr.course = sr2.course)
Das not exists ist vielleicht die Lösung, aber es wird ja durch die “recht offene” Einschränkung zurück sr gender, styleid und course irgendwie ins Knie getreten.
Überhaupt finde ich den Join über die 3 Felder sehr schwach. Fehlt vielleicht ein join kriterium? Und muss wirklich alles Outer sein?
Und wäre ri.recordlistid = 50069 nicht eher where clause?
Erstens: weils potentielle Fehler zukleistert. Meist sind Dubletten nämlich ein Zeichen dafür, daß man sich irgendwo verJOINt hat und z.B. ein INNER JOIN setzen sollte oder irgendein Join-Kriterium fehlt.
Zweitens: weil nur wenige RDBMS-Optimizer bei DISTINCT merken, wenn es nutzbare Indices über die fraglichen Spalten gibt. Deshalb ist häufig (nicht immer!) ein GROUP BY die bessere Option.
Also z.B. statt
SELECT DISTINCT ID, NAME FROM PERSON
lieber gruppieren:
SELECT ID,NAME FROM PERSON GROUP BY ID,NAME.
Liefert das gleiche Ergebnis, lotst aber die meisten RDBMS direkt dazu, vorhandene Indices für ID und Name zu nutzen. Bei DISTINCT mußt Du Glück haben daß der Optimizer gut genug ist.
Bei der einen Tabelle bringt das noch nicht wirklich was weil man da eh einen Table Scan braucht, aber wenn man das mit ein paar JOINs kombiniert sieht der EXPLAIN ANALYZE da schnell ganz anders aus.
EXIST oder IN statt LEFT JOIN müßte eigentlich im Zweifelsfall eher noch langsamer sein, weil die Subquery dann auf Row Level wiederholt ausgeführt werden muß.