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

Comment améliorer les performances des requêtes (à l'aide des résultats de la commande d'explication, par exemple)

Vous pouvez essayer quelque chose comme ça (bien que ce ne soit pas pratique pour moi de tester ça)

SELECT
    sac.surveyId,
    q.cat,
    SUM((sac.answer_id*q.weight))/SUM(q.weight) AS score,
    user.division_id,
    user.unit_id,
    user.department_id,
    user.team_id,
    division.division_name,
    unit.unit_name,
    dpt.department_name,
    team.team_name
FROM survey_answers_cache sac
    JOIN
    (
        SELECT
            s.surveyId,
            sc.subcluster_id
        FROM
            surveys s
            JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
            JOIN cluster c ON sc.cluster_id = c.cluster_id
        WHERE
            c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
    ) AS v ON v.surveyid = sac.surveyid
    JOIN user ON user.user_id = sac.user_id
    JOIN questions q ON q.question_id = sac.question_id
    JOIN division ON division.division_id = user.division_id
    LEFT JOIN unit ON unit.unit_id = user.unit_id
    LEFT JOIN department dpt ON dpt.department_id = user.department_id
    LEFT JOIN team ON team.team_id = user.team_id
GROUP BY user.team_id, v.surveyId, q.cat
ORDER BY v.surveyId, user.team_id, q.cat ASC

J'espère donc que je n'ai rien gâché.

Quoi qu'il en soit, l'idée est que dans la requête interne, vous ne sélectionnez que les lignes dont vous avez besoin en fonction de votre condition where. Cela créera une table tmp plus petite car elle ne tire que 2 champs à la fois int.

Ensuite, dans la requête externe, vous vous joignez aux tables dont vous extrayez réellement le reste des données, l'ordre et le groupe. De cette façon, vous triez et regroupez sur un ensemble de données plus petit. Et votre clause where peut s'exécuter de la manière la plus optimale.

Vous pourrez peut-être même omettre certaines de ces tables car vous ne tirez que des données de quelques-unes d'entre elles, mais sans voir le schéma complet et son lien, c'est difficile à dire.

Mais d'une manière générale, cette partie (La sous-requête)

SELECT
    s.surveyId,
    sc.subcluster_id
FROM
    surveys s
    JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
    JOIN cluster c ON sc.cluster_id = c.cluster_id
WHERE
    c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0

Est ce qui est directement affecté par votre clause WHERE. Voir afin que nous puissions optimiser cette partie puis l'utiliser pour joindre le reste des données dont vous avez besoin.

Un exemple de suppression de tables peut être facilement déduit de ce qui précède, considérez ceci

SELECT
    s.surveyId,
    sc.subcluster_id
FROM
    surveys s
    JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
WHERE
    sc.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0

Le c table cluster n'est jamais utilisé pour extraire des données, uniquement pour où. Donc n'est-ce pas

    JOIN cluster c ON sc.cluster_id = c.cluster_id
 WHERE
    c.cluster_id=?

Identique ou équivalent à

WHERE
    sc.cluster_id=?

Et donc nous pouvons éliminer complètement cette jointure.