Joomla SQL

2011-05-19 12:06

Joomla 1.6 versijos administracinės dalies faile administrator/components/com_menus/models/menus.php yra metodas getListQuery(), kuris kažkurioje admininistracinės dalies vietoje sugeneruoja ir vykdo tokią užklausą:

SELECT a.*, COUNT(DISTINCT m1.id) AS count_published, COUNT(DISTINCT m2.id) AS count_unpublished, COUNT(DISTINCT m3.id) AS count_trashed
FROM `j16_menu_types` AS a
LEFT JOIN `j16_menu` AS m1 ON m1.menutype = a.menutype
AND m1.published =1
LEFT JOIN `j16_menu` AS m2 ON m2.menutype = a.menutype
AND m2.published =0
LEFT JOIN `j16_menu` AS m3 ON m3.menutype = a.menutype
AND m3.published = -2
GROUP BY a.id

Tai labai baisi užklausa (ne sudėtingumo,  bet serveriui duodamo darbo prasme), kuri naudotame MySQL serveryje vykdoma ne mažiau kaip 16s(!). MySQL lėtų užklausų žurnale matyti, jog kartais ši užklausa vykdoma net daugiau kaip 10 minučių (!!!).

Pamėginta sumažinti duomenų gavimo laiką.

Pirmiausia SQL suskaidyta į mažesnius blokus, vienoje užklausoje skaičiuojant tik vieno stulpelio skaičių.

SELECT a.*, COUNT(DISTINCT m1.id) AS count_published
FROM `j16_menu_types` AS a
LEFT JOIN `j16_menu` AS m1 ON m1.menutype = a.menutype
AND m1.published = 1
GROUP BY a.id

Tokia užklausa įvykdyta per mažiau nei 0,05s.

Sulipdytas SQL, jog tie patys duomenys (tik kitaip išdėstyti) būtų gaunami viena SQL užklausa:

SELECT a.*, COUNT(DISTINCT m1.id) AS count, ‘published’ AS type FROM `j16_menu_types` AS a
LEFT JOIN `j16_menu` AS m1 ON m1.menutype=a.menutype AND m1.published=1
GROUP BY a.id
UNION
SELECT a.*, COUNT(DISTINCT m1.id) AS count, ‘unpublished’ AS type FROM `j16_menu_types` AS a
LEFT JOIN `j16_menu` AS m1 ON m1.menutype=a.menutype AND m1.published=0
GROUP BY a.id
UNION
SELECT a.*, COUNT(DISTINCT m1.id) AS count, ‘trashed’ AS type FROM `j16_menu_types` AS a
LEFT JOIN `j16_menu` AS m1 ON m1.menutype=a.menutype AND m1.published=-2
GROUP BY a.id

Šios sulipdytos SQL užklausos vykdymo laikas trunka apie 0,1s. Gautas pagreitėjimas nuo 200 iki 6000 KARTŲ!