Thorsten: Umkreissuche sehr langsam

Beitrag lesen

yo,

ich gebe zu, dass ich auch nicht der klassen-primus von sql-schreibstil bin, aber deine schreibeweise ist grausam, viel zu sehr gestreckt.

Jede so wie er es mag oder?

SELECT o.ort, o.plz
FROM orte AS o
INNER JOIN event AS e ON o.plz = e.plz
INNER JOIN event_kat AS k ON e.kat_id = k.kat_id
LEFT JOIN bilder AS b ON e.event_id = b.event_id OR b.event_id IS NULL
WHERE e.gespert = 0
AND 6367.41*SQRT(2*(1-cos(RADIANS(breite))
    *cos(".$breite.")
    *(sin(RADIANS(laenge))
    *sin(".$laenge.")+cos(RADIANS(laenge))
    *cos(".$laenge."))-sin(RADIANS(breite))
    *sin(".$breite."))) <= ".$umkreis."
OR e.plz = '$plz'
ORDER BY Distance
;

ok, das reicht erst mal für testzwecke, du musst die projektion erst enimal nicht mit lauter spalten verkomplizieren, für die geschwindigkeit ist sie in aller regel zu vernachläßigen.

nnu aber zu deinem problem,  tuning bedeutet probieren geht über studieren. ich kann das nicht oft genug betonen, es gibt keine patentlösung. unterschiedliche dbms, versionen, designs und dateninhalte verhalten sich anders und macht es schwierig, allgemeingültige regeln aufzustellen.

aber das erste was ich machen würde, die OR bedingung in einen UNION ALL auslagern, sprich du hast zweimal die gleiche abfrage. beide abfragen würde ich auf performance erst einmal einzeln testen. Auch die Sortierung würde ich erst einmal wegfallen lassen.

SELECT o.ort, o.plz
FROM orte AS o
INNER JOIN event AS e ON o.plz = e.plz
INNER JOIN event_kat AS k ON e.kat_id = k.kat_id
LEFT JOIN bilder AS b ON e.event_id = b.event_id OR b.event_id IS NULL
WHERE e.gespert = 0
AND 6367.41*SQRT(2*(1-cos(RADIANS(breite))
    *cos(".$breite.")
    *(sin(RADIANS(laenge))
    *sin(".$laenge.")+cos(RADIANS(laenge))
    *cos(".$laenge."))-sin(RADIANS(breite))
    *sin(".$breite."))) <= ".$umkreis."
UNION ALL
SELECT o.ort, o.plz
FROM orte AS o
INNER JOIN event AS e ON o.plz = e.plz
INNER JOIN event_kat AS k ON e.kat_id = k.kat_id
LEFT JOIN bilder AS b ON e.event_id = b.event_id OR b.event_id IS NULL
WHERE e.plz = '$plz'
;

Im ersten Union teil benutzt due funktionen in der WHERE klausel, das führt in aller regel zu dem problem, dass ein index nicht genutzt werden kann, es sei den, es ist ebenfalls eni funktionaler index. keine ahnung, ob mysql das in der version kann. Auf jeden fall musst du dir den ausführungsplan anschauen, den das dbms ausführt und dann sieht man weiter.

Wie kann ich mir den Ausführungsplan genau anschauen? Mit Explain?

Kritisch könnte auch der LEFT JOIN sein, versuche beiden abfragen des Unions mal ohne ihn, vor allem mit der OR verbindnug drinne.

Letztlich musst du dir auch überlegen, ob du die gleiche ergebnismenge nicht auch mit einer "besseren" abfrage bekommen kannst.

Ich habe jetzt deine 2 Abfrage mal losgelassen vorher die gesätzen Indexe entfernt.
Bei 17200 Datensätzen bekahm ich zumindest mal eine Antwort dauer ca. 20 sek.

Weiter habe ich dann ein Index auf event.plz gesätzt und auf orte.plz. dabei gab es keine Antwort mehr der Server hat sich wechgehangen warum auch immer.

Also habe ich nur einen Index auf event. plz gesätzt und siehe da inhalb von 2 sek eine Antwort. Jetzt werde ich mal langsam die Datensätze erhöhen mal sehen wie sich das verhält.

Den Left join habe ich herausgenommen kein unterschied.

Ich danke dir erstmal für deine sehr Hilfreichen Beitrag und werde weiter Testen :)

Ilja