MySQL Cross Join vs. Inner join

Dieser Thread im g:b brachte mich auf die spontane Idee, doch mal den angeblichen Performanceunterschied zwischen einem Herkömmlichen Cross Join (oder Equi-Join) mit einem Inner Join, der speziell in der MySQL Syntax ist, zu vergleichen.
Grundlage dazu ist eines meiner aktuellen Probleme mit Datenbankperformance. Es geht um die Entfernungsberechnung mittels der OpenGEOdb.

Ich will jetzt hier keine endlos langen CREATE TABLE Abschnitte posten, die die Tabellenstruktur abbilden (bei Bedarf kann ich das aber nachholen), aber soviel zu den Tabellen und zum Problem sei gesagt: Es geht darum, eine Postleitzahl einzugeben. Anhand dieser PLZ sollen dann alle Einträge der tabelle tx_cal_event ausgegeben werden, deren PLZ innerhalb eines Radius von 50 km von der angegeben Postleitzahl liegt.

Die Abfrage dazu sieht in der ‚herkömmlichen‘ Equi-Join Syntax so aus:

SELECT DISTINCT cal.title, cal.uid,
acos(sin(gcb.lat*(pi()/180))*sin(gc.lat*(pi()/180))+cos(gcb.lat*(pi()/180))*cos(gc.lat*(pi()/180))*cos((gcb.lon*(pi()/180)) – (gc.lon*(pi()/180)))) * 6380 AS distanz1
FROM tx_cal_event cal, geodb_textdata gt, geodb_textdata gtb, geodb_coordinates gc, geodb_coordinates gcb
WHERE gc.loc_id = gt.loc_id
AND gt.text_val = 59302
AND gt.text_type = 500300000
AND cal.plz = gtb.text_val
AND gcb.loc_id = gtb.loc_id
AND gtb.text_type = 500300000
HAVING distanz1 < 50 [/code]

Die eingegebene PLZ ist hier die 59302. Gemittelt auf 10 Abfragen dauert die Darstellung des Ergebnisses:

+-----------+-----+------------------+
| title     | uid | distanz1         |
+-----------+-----+------------------+
| Bielefeld |   6 | 35.7018994867162 | 
| Münster   |  64 | 39.2383884821436 | 
| Bielefeld |  87 | 35.7018994867162 | 
+-----------+-----+------------------+
3 rows in set

Sage und schreibe 8.5250 Sekunden.

Jetzt das Gegenbeispiel (?) mit der INNER JOIN Syntax:

SELECT DISTINCT cal.title, cal.uid,
acos(sin(gcb.lat*(pi()/180))*sin(gc.lat*(pi()/180))+cos(gcb.lat*(pi()/180))*cos(gc.lat*(pi()/180))*cos((gcb.lon*(pi()/180)) – (gc.lon*(pi()/180)))) * 6380 AS distanz1
FROM tx_cal_event cal
INNER JOIN geodb_textdata gt ON gt.text_val = 59302 AND gt.text_type = 500300000
INNER JOIN geodb_textdata gtb ON gtb.text_val = cal.plz AND gtb.text_type = 500300000
INNER JOIN geodb_coordinates gc ON gt.loc_id = gc.loc_id
INNER JOIN geodb_coordinates gcb ON gtb.loc_id = gcb.loc_id
HAVING distanz1 < 50 [/code]

Dauerte bei 10 Abfragen im Mittel (beim natürlich selben Ergebnis) 8.4442 Sekunden. *tusch*

Wir halten fest: Keine merklichen Perfomaceunterschiede in Cross Join oder Inner Join Syntax. Schade eigentlich.

Achja: Wer noch eine Lösung kennt, diese Abfrage zu beschleunigen (knapp 9 Sekunden!!) möge sich doch bitte bei mir melden 😉

6 Kommentare to “MySQL Cross Join vs. Inner join”

  1.  crash[kid] schrieb am 03. Jan 2007 um 23:50

    Ich wundere mich immer noch, warum das in dem von dir genannten Thread im gulli:board, der mein Problem behandelt, so viel laenger gedauert hat. Bei mir lag das naemlich sicherlich nicht im Millisekundenbereich, sondern die normale JOIN-Methode war schon _deutlich_ langsamer als die, die INNER JOIN benutzt.

    Ich werde mir bei Gelegenheit (morgen?) nochmals beide Statements aus dem Thread genauer anschauen, denn irgendwo muss ein Fehler sein. Nach deiner Analyse muessen beide Abfragen annaehernd gleich schnell bearbeitet werden. Es muss also einen Fehler geben … irgendwo!

    Btw: ich finde die SQL-Abfragen hier in diesem Beitrag etwas zu klein dargestellt. Vielleicht kannst du die Schriftgroeße, die dort verwendet wird, im Stylesheet etwas groeßer definieren.

  2.  Greg schrieb am 04. Jan 2007 um 0:07

    Btw: ich finde die SQL-Abfragen hier in diesem Beitrag etwas zu klein dargestellt. Vielleicht kannst du die Schriftgroeße, die dort verwendet wird, im Stylesheet etwas groeßer definieren.

    Besser?

  3.  crash[kid] schrieb am 04. Jan 2007 um 10:50

    Besser?

    Ja, so ist es wunderbar. Danke 🙂

  4.  Jochen Weiland schrieb am 18. Feb 2007 um 23:20

    Ich musste für ein TYPO3 Projekt heute auch so eine Umkreissuche implementieren. Das Geschwindigkeitsproblem habe ich dadurch gelöst, dass ich zunächst einen Datenbankabfrage mache, in der ich zunächst grob ein Quadrat um die eigene PLZ lege (Breiten/Längengrad +/- Faktor) und dann nur die Entfernungen zu den Postleitzahlen innerhalb dieses Quadrats berechne.
    Wenn ich Zeit habe, mache ich in den nächsten Wochen eine öffentliche Extension draus und lade sie ins TER

  5.  robotics schrieb am 15. Mrz 2009 um 20:39

    Auszug von http://dev.mysql.com/doc/refman/5.1/de/join.html:

    In MySQL ist CROSS JOIN syntaktisch ein Äquivalent zu INNER JOIN (diese lassen sich gegeneinander austauschen)

    In Mysql sind werden beide Befehle gleich interpretiert…

  6.  Jan Brinkmann schrieb am 18. Dez 2010 um 0:09

    Hallo

    Ich bin durch Zufall auf diesem Artikel gestossen. Wie bereits von „robotics“ durch den Verweis auf die MySQL Doku richtig dargestellt, sind die Keywords austauschbar. Nun zu meinem Anliegen:

    Ich wurde bereits mehrfach auf MySQL Joins angesprochen, sowohl beruflich als auch privat. Da ich keine Seite gefunden habe, auf der einfach mal alle Join Typen auch für „Einsteiger“ verständlich erläutert werden, habe ich eine solche Seite selbst erstellt:

    - http://mysql-join.com

    Da ich hier versuchen möchte eine optimale Referenz für erfahrene Entwickler mit einer verständlichen Einleitung für unerfahrene(re) Entwickler zu erschaffen, benötige ich Feedback von anderen. Bei der Recherche nach geeigneten Ansprechpartnern bin ich auf diesen Artikel gestossen. Über Feedback würde ich mich wirklich sehr freuen. Was denken andere?:

    - Wie ist der Inhalt?
    - Alles schlüssig erläutert?
    - Was sollte man verbessern?
    - usw.

    Herzlichen Dank vorab!

    Jan

Trackback-Adresse | RSS-Feed für die Kommentare abonnieren

Hinterlasse einen Kommentar:


(Wir behalten uns vor Kommentare von dummen Menschen entweder zu löschen oder exemplarisch für die Nachwelt zu konservieren. Dumme Kommentare mit Werbelinks müssen leider auf zweiteres Privileg verzichten.)

XHTML: Du kannst diese Tags verwenden:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>