Mysql
 sql >> Base de données >  >> RDS >> Mysql

Requête lente avec la clause HAVING - puis-je l'accélérer ?

Une solution rapide serait de filtrer dans la sous-requête :

SELECT count(d.id) AS dcount, s.id, s.name
FROM sites s
LEFT JOIN deals d ON (s.id = d.site_id AND d.is_active = 1)
WHERE (s.is_active = 1)
AND s.id IN(
    SELECT g.site_id
    FROM gstats g
    WHERE g.start_date > '2015-04-30' AND g.site_id = s.id
    GROUP BY g.site_id
    HAVING SUM(g.results) > 100
)
GROUP BY s.id
ORDER BY dcount ASC

Sinon, vous effectuez une telle requête de regroupement pour chaque candidat possible. Nous pouvons rendre cela plus élégant avec EXISTS :

SELECT count(d.id) AS dcount, s.id, s.name
FROM sites s
LEFT JOIN deals d ON (s.id = d.site_id AND d.is_active = 1)
WHERE (s.is_active = 1)
AND EXISTS (
    SELECT 1
    FROM gstats g
    WHERE g.site_id = s.id AND g.start_date > '2015-04-30'
    HAVING SUM(g.results) > 100
)
GROUP BY s.id
ORDER BY dcount ASC

Mais nous n'avons pas encore fini, maintenant nous allons utiliser le EXISTS pour chaque élément. C'est bizarre puisque la requête ne dépend que de s.id , cela ne dépend donc que du groupe , pas les lignes individuelles. Donc un potentiel accélérer, mais cela dépend de la taille des tables, etc. est de déplacer la condition vers un HAVING déclaration :

SELECT count(d.id) AS dcount, s.id, s.name
FROM sites s
LEFT JOIN deals d ON (s.id = d.site_id AND d.is_active = 1)
WHERE (s.is_active = 1)
GROUP BY s.id
ORDER BY dcount ASC
HAVING EXISTS (
    SELECT 1
    FROM gstats g
    WHERE g.site_id = s.id AND g.start_date > '2015-04-30'
    HAVING SUM(g.results) > 100
)