Mysql
 sql >> Database >  >> RDS >> Mysql

Come migliorare le prestazioni della query (usando il comando spiega i risultati, ad es.)

Puoi provare qualcosa del genere (anche se per me non è pratico testarlo)

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

Quindi spero di non aver sbagliato nulla.

Ad ogni modo, l'idea è che nella query interna selezioni solo le righe di cui hai bisogno in base alla tua condizione where. Questo creerà una tabella tmp più piccola poiché estrae solo 2 campi entrambi gli int.

Quindi nella query esterna ti unisci alle tabelle da cui estrai effettivamente il resto dei dati, ordina e raggruppa. In questo modo stai ordinando e raggruppando su un set di dati più piccolo. E la tua clausola where può essere eseguita nel modo più ottimale.

Potresti anche essere in grado di omettere alcune di queste tabelle come unico prelievo di dati da alcune di esse, ma senza vedere lo schema completo e come è correlato è difficile da dire.

Ma in generale questa parte (la sottoquery)

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

È ciò che è direttamente influenzato dalla tua clausola WHERE. Vedi così possiamo ottimizzare questa parte, quindi usarla per unire il resto dei dati di cui hai bisogno.

Un esempio di rimozione delle tabelle può essere facilmente dedotto da quanto sopra, considera questo

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

Il c tabella cluster non viene mai utilizzato per estrarre i dati da, solo per il dove. Così non è

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

Uguale o equivalente a

WHERE
    sc.cluster_id=?

E quindi possiamo eliminare completamente quell'unione.