phpbar.de logo

Mailinglisten-Archive

Re: Joins / Performance
Archiv Mailingliste mysql-de

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Joins / Performance



Andreas Kempf aka 'amalesh' schrieb am Donnerstag, den 19. August 1999:
> auf http://www.problemloeser.de/d1.htm habe ich einen artikel
> gefunden, wie joins optimiert werden können.

Der Artikel ist in dieser Form - ohne Bezug zu einem konkreten DBMS -
sehr irreführend, denn ob bei der Ausführung der vom Ergebnis her
identischen Anweisungen
   FROM a, b WHERE a.id=b.id ...
und
   FROM a JOIN b ON a.id=b.id WHERE ...
intern ein Unterschied gemacht wird, hängt rein von der
Implementierung und evtl. Optimierungen des DBMS ab.

> Überraschender weise ist das ergebnis mit mySQL jedoch anders, als
> (für andere DB's?) vorhergesagt.

Speziell in Bezug zu MySQL ist der Artikel sogar wertlos, da MySQL eh
_nur_ die Kommaform anbietet.

Der LEFT JOIN, den Du hernach verwendest, ist etwas anderes als ein
normaler JOIN!

> Ziel: Ich will die personenanzahl aller orte, in denen die personen
> keiner niederlassung angehören. Dazu habe ich folgendes statement:
> 
> select distinct(a.ort), count(a.id) as anzahl 
>   from person a, 
>        rel_niederlassung_person b 
>  where a.id != b.person_id 
>  group by ort 
>  order by ort

Vorbemerkung:
   DISTINCT(ort), ... tut etwas anderes, als Du vermutlich willst
   (schließe ich aus der Klammernsetzung), denn
     SELECT DISTINCT ... FROM
   bedeutet (zumindest in MySQL), daß die Ergebnistupel gesamt (also
   alle Ergebnisfelder als ein Wert zusammengenommen) unterschiedlich
   sein müssen (die Klammern um a.ort sind für MySQL hier also kein
   Teil von DISTINCT, sondern einfach unnötige, aber auch nicht
   störende Klammern um a.ort). Somit wären (Passau, 5) und (Passau,
   6) mögliche Ergebnisse.  In Deinem Beispiel kann aber aufgrund des
   GROUP BY eh kein doppelter Ort vorkommen, weshalb Du das so nicht
   bemerken wirst.

Zur SQL-Anfrage selbst:
   Das funktioniert wirklich so?  Kann ich nicht recht glauben ...

   Wenn ich das richtig verstehe, wird doch so pro Ort und pro Person
   dieses Ortes jede andere in der Tabelle "rel_niederlassung_person"
   vorkommende Person gezählt!

   Das ist nicht, was Du oben als Ziel angibst!

   Mein Lösungsvorschlag:

   SELECT a.ort, COUNT(*) AS anzahl
   FROM person AS a LEFT JOIN rel_niederlassung_person AS b
        ON a.id = b.id
   WHERE b.id IS NULL
   GROUP BY a.ort;

   Das liefert Dir pro Ort die Anzahl der Leute, die nicht in der
   Tabelle "rel_niederlassung_person" aufgeführt sind.

   Oder wolltest Du nur die Orte, wo keine Person einer Niederlassung
   angehört (plus die Anzahl dieser Leute)?  Dann das hier:

   SELECT a.ort, COUNT(*) AS anzahl
   FROM person AS a LEFT JOIN rel_niederlassung_person AS b
        ON a.id = b.id
   GROUP BY a.ort
   HAVING COUNT(b.id)=0;


> Tabelle person enthält ca. 4000 records. Ergebnis: 0.60 sekunden
> execution time
> 
> Wenn ich hingegen [...]
>    select distinct(a.ort), count(a.id) as anzahl 
>      from person a 
> left join rel_niederlassung_person b 
>        on a.id != b.person_id 
>     group by ort 
>     order by ort 
> benutze, komme ich auf 0.88 sek. execution time.

Dieser Zeitunterschied dürfte einfach daher kommen, daß bei dem LEFT
JOIN mehr kombinierte Datensätze entstehen, also auch mehr zu
gruppieren und zählen ist.

Ciao,
  Martin
-- 
Martin Ramsch <m.ramsch_(at)_computer.org> <URL: http://home.pages.de/~ramsch/ >
PGP KeyID=0xE8EF4F75 FiPr=52 44 5E F3 B0 B1 38 26  E4 EC 80 58 7B 31 3A D7

---
*** Abmelden von dieser Mailingliste funktioniert per E-Mail
*** an mysql-de-request_(at)_lists.4t2.com mit Betreff/Subject: unsubscribe


Home | Main Index | Thread Index

php::bar PHP Wiki   -   Listenarchive