使用一些连接,PHP PDO在SELECT上太慢了

时间:2015-04-08 14:27:52

标签: php mysql performance pdo

我在PHP PDO中执行select时遇到了性能问题。

使用stackoverflow(Simplest way to profile a PHP script)提供的脚本,我确定了问题所在,但我没有找到解决方案。

我选择的问题是:

SELECT REDACAO.ID_REDACAO AS ID_REDACAO, 
    DATE_FORMAT(REDACAO.DATA,'%d/%m/%Y') AS DATAE, 
    ALUNO.ID_ALUNO AS ID_ALUNO, 
    (SELECT IFNULL((DATEDIFF(DATE_ADD((SELECT MAX(DATA) FROM REDACAO WHERE ID_ALUNO = ALUNO.ID_ALUNO AND ID_REDACAO NOT IN (SELECT ID_REDACAO FROM CORRECAO)), INTERVAL 7 DAY), now())),NULL) as DATA FROM REDACAO LIMIT 1) AS ULTIMA, 
    ALUNO.NOME as ALUNO, 
    REDACAO.ID_TEMA AS ID_TEMA,
    TEMA.TITULO as TEMA,
    TEMA.MOTIVACIONAIS AS MOTIVACIONAIS, 
    REDACAO.TEXTO AS TEXTO, 
    REDACAO.ID_STATUS AS STATUS,
    B.NOTA as NOTA, 
    B.RCORRIGIDA AS CORRIGIDA,
    B.NOTA1,
    B.COMENTARIO1,
    B.NOTA2,
    B.COMENTARIO2,
    B.NOTA3,
    B.COMENTARIO3,
    B.NOTA4,
    B.COMENTARIO4,
    B.NOTA5,
    B.COMENTARIO5,
    B.COMENTARIO6,
    C.COMENTARIO AS COMENTARIO 
FROM REDACAO 
    LEFT OUTER JOIN (SELECT SUM(CORRECAO.C1+CORRECAO.C2+CORRECAO.C3+CORRECAO.C4+CORRECAO.C5) AS NOTA, RCORRIGIDA AS RCORRIGIDA, CORRECAO.C1 as NOTA1, CORRECAO.COM1 as COMENTARIO1, CORRECAO.C2 as NOTA2, CORRECAO.COM2 as COMENTARIO2, CORRECAO.C3 as NOTA3, CORRECAO.COM3 as COMENTARIO3, CORRECAO.C4 as NOTA4, CORRECAO.COM4 as COMENTARIO4, CORRECAO.C5 as NOTA5, CORRECAO.COM5 as COMENTARIO5, CORRECAO.COMGERAL AS COMENTARIO6, CORRECAO.ID_REDACAO FROM CORRECAO GROUP BY CORRECAO.ID_REDACAO) B 
    ON B.ID_REDACAO = REDACAO.ID_REDACAO 
    JOIN ALUNO ON ALUNO.ID_ALUNO = REDACAO.ID_ALUNO 
    JOIN TEMA ON TEMA.ID_TEMA = REDACAO.ID_TEMA 
    LEFT OUTER JOIN (SELECT (COUNT(COMENTARIO.ID_COMENTARIO)) AS COMENTARIO, COMENTARIO.ID_REDACAO FROM COMENTARIO GROUP BY COMENTARIO.ID_REDACAO) C 
    ON C.ID_REDACAO = REDACAO.ID_REDACAO 
WHERE REDACAO.ID_PROFESSOR = $CodProfessor 
    and REDACAO.ID_STATUS != 6 
ORDER BY (CASE WHEN REDACAO.ID_STATUS = 4 THEN 1 ELSE 0 END) DESC

我正在使用(PDO :: FETCH_ASSOC)来获取数据。有些列的响应时间不到1秒,其他列则超过20秒。

知道可能是什么问题以及如何解决它?

2 个答案:

答案 0 :(得分:2)

您的查询包含以下内容会降低速度:

  • 很多加入
  • 许多子选择
  • 选择不在哪里
  • 函数如COUNT,isnull,datediff,sum。(其中一些可能取消索引)
  • 案例何时
  • 通过
  • 订购
  • group by

根据您的索引,表格的连接方式以及表格的大小,这最终会变得非常慢。

尝试使用'explain'命令,并尽可能简化查询。

explain output

a good video about explain

答案 1 :(得分:0)

PDO没有错;查询很复杂。并且可能缺少索引。

将其变为LEFT JOIN(因为IN (SELECT...)优化效果不佳。

AND  ID_REDACAO NOT IN (  SELECT  ID_REDACAO FROM  CORRECAO)

升级到5.6;它有一些改进。

你有两个JOIN ( SELECT ... )。在5.6之前,将进行非常优化。将其中一个移出到临时表中,您可以向其添加合适的索引。

在其中一个子查询中,GROUP BY CORRECAO.ID_REDACAO似乎是不必要的。

需要这些索引(或PRIMARY KEYs):

  • CORRECAO:(ID_REDACAO)
  • REDACAO:(ID_REDACAO),(ID_PROFESSOR)
  • ALUNO:(ID_ALUNO)
  • TEMA:(ID_TEMA)
  • COMENTARIO:(ID_REDACAO,ID_COMENTARIO)(“复合指数”)

如果这些建议不够用,请为每个表返回SHOW CREATE TABLE。