Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como melhorar o desempenho da consulta (usando os resultados do comando de explicação f.e.)


Você pode tentar algo assim (embora não seja prático para mim testar isso)
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

Então espero não ter estragado nada.

De qualquer forma, a ideia é na consulta interna você selecionar apenas as linhas necessárias com base na sua condição where. Isso criará uma tabela tmp menor, pois apenas puxa 2 campos em ambos os ints.

Em seguida, na consulta externa, você une as tabelas das quais você realmente extrai o restante dos dados, ordena e agrupa. Dessa forma, você está classificando e agrupando em um conjunto de dados menor. E sua cláusula where pode ser executada da maneira mais otimizada.

Você pode até conseguir omitir algumas dessas tabelas como sua única extração de dados de algumas delas, mas sem ver o esquema completo e como ele está relacionado, é difícil dizer.

Mas de um modo geral esta parte (A sub-consulta)
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

É o que é diretamente afetado pela sua cláusula WHERE. Veja para que possamos otimizar essa parte e depois usá-la para juntar o restante dos dados que você precisa.

Um exemplo de remoção de tabelas pode ser facilmente deduzido do acima, considere isso
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

O c tabela cluster nunca é usado para extrair dados, apenas para onde. Então não é
    JOIN cluster c ON sc.cluster_id = c.cluster_id
 WHERE
    c.cluster_id=?

Igual ou equivalente a
WHERE
    sc.cluster_id=?

E, portanto, podemos eliminar essa junção completamente.