Converting fast query with subquery to joined query for mysql-4.0.x
am 15.10.2006 21:17:28 von Henri SchomaeckerHallo alle zusammen,
um aus einem oscommerce Shopsystem aus tausenden von Kunden diejenigen
herauszusuchen, die sich zwar angemeldet, aber noch keinerlei Bestellung
aufgegeben haben, hab´ ich eine Abfrage geschrieben die sehr schnell ist
und eine Subquery enthält.
Dummerweise hab´ ich hierbei aber nicht bedacht, dass der Shop des
Kunden, der dies bestellt hat, noch auf einem unserer älteren Server
liegt der noch, allerdings aus gutem Grund, mit MySql-4.0.x bestückt ist.
Hier funktionieren Subqueries ja aber leider noch nicht, also hab ich
begonnen, die Query in eine umzuschreiben, die Joins verwendet.
Leider ist diese, LEFT JOINs verwendende Abfrage extreeeeem langsam und
ausserdem benötigt der Prozess dann ca 94% der CPU und ca. 40 MB im
Speicher. - Das war aber natürlich nicht Sinn der Übung ;-)
Ausserdem werden auch ein paar komplett leere Datenzeilen ausgegeben,
was auch nicht so schön ist.
Oft hilft bei JOINs beinhaltenden Queries schon eine Umstellung der
JOINs, was aber hier nicht geholfen hat.
Ich würde mich sehr freuen, wenn mir jemand bei einer besseren Umsetzung
helfen könnte und mir erklärt, warum die zweite Abfrage soooo
Ressourcenaufwändig ist und wie's besser ginge.
Hier einmal Beispiele (Extrem gekürzt!) für beide Abfragen...
Query mit Sub-Select:
8<--------8<--------8<--------8<--------8<--------8<--------
select DISTINCT
`c`.`customers_id`,
`c`.`customers_firstname`,
`c`.`customers_lastname`,
`address_book`.`entry_company`,
`countries`.`countries_name`
FROM `customers` `c`, `address_book`, `countries`
WHERE `address_book`.`customers_id` = `c`.`customers_id`
AND `address_book`.`address_book_id` = `c`.`customers_default_address_id`
AND `countries`.`countries_id` = `address_book`.`entry_country_id`
AND `c`.`customers_id` not in (SELECT DISTINCT `orders`.`customers_id`
FROM `orders`)
ORDER BY `c`.`customers_lastname` desc
8<--------8<--------8<--------8<--------8<--------8<--------
Query mit Left-Joins (Klappt, ist aber extrem langsam!)
8<--------8<--------8<--------8<--------8<--------8<--------
SELECT DISTINCT
`c`.`customers_id`,
`c`.`customers_firstname`,
`c`.`customers_lastname`,
`address_book`.`entry_company`,
`countries`.`countries_name`
FROM `customers` `c`
LEFT JOIN `address_book` on
`c`.`customers_default_address_id`=`address_book`.`address_b ook_id`
LEFT JOIN `countries` on
`address_book`.`entry_country_id`=`countries`.`countries_id`
LEFT JOIN `orders` on `c`.`customers_id`=`orders`.`customers_id`
WHERE `orders`.`customers_id` IS NULL
ORDER BY `c`.`customers_lastname` asc
8<--------8<--------8<--------8<--------8<--------8<--------
vielen herzlichen Dank schon einmal im Voraus,
Gruss Henri