Ilja: 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.

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.

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.

Ilja