On Thu, Apr 14, 2005 at 07:13:32PM +0200, Wiktor R. Braun wrote:
Witam, proszę o pomoc w optymalizacji zapytania MySQL'owego. Aktualnie trwa zbyt długo... ~20 sek.
Taka sztuczka z mysqlem jest...
- zostali podłączeni przed 2005 rokiem,
Ze w users jest "creationdate" co już prawie dobrze użyłeś...
- mają włączone komputery,
- bez zawieszonych płatności :)
LMS v1.4.x
SELECT users.id AS id, CONCAT(UPPER(lastname), ' ', users.name) AS username, status, email, phone1, phone2, phone3, users.address, gguin, nip, pesel, zip, city, info, message, serviceaddr,
Sztuczka polega na tym aby tutaj pobierać tylko i wyłącznie user id
COALESCE(SUM((type * -2 + 7) * value), 0.00)/(CASE COUNT(DISTINCT nodes.id) WHEN 0 THEN 1 ELSE COUNT(DISTINCT nodes.id) END) AS balance FROM users LEFT JOIN cash ON (users.id=cash.userid AND (type = 3 OR type = 4))
I złączyć cash, można pokusić się wcześniej o time >= 1104534000 (timestamp z Sylwestra 2004).
Tylko że zrobić to do tabelki tymczasowej ( "DROP TABLE tmp_users; CREATE TEMPORARY TABLE tmp_users SELECT ...")
LEFT JOIN nodes ON (users.id=ownerid)
Zrób to jeszcze *przed* złączaniem cash. Tzn tmp_users jako tabelkę userid takich że mają włączone komputery.
LEFT JOIN assignments ON (users.id=assignments.userid) WHERE deleted = 0
Potem zrób delete from tmp_users gdy nie mają oni obciążeń (cały czas na tabelce tymczasowej).
ORDER BY balance asc
Dopiero teraz zrób policzenie salda i potem złącz to z *potrzebnymni* danymi z users. Na czas tych operacji dobrze jest albo zalockować tabelki tylko-do-odczytu albo po prostu uznać że nikt Ci nie dopisze co cash nic. Aha: mysql już tak ma.
kd.