Pergunta

Os trava seguinte consulta: (embora subqueries perfomed separadamente são muito bem)

Eu não sei como fazer o ok tabela de procura explicar. Se alguém me diz, eu vou limpá-lo.

select
sum(grades.points)) as p,  
from assignments 
left join grades using (assignmentID) 
where gradeID IN 

(select grades.gradeID 
from assignments 
left join grades using (assignmentID) 
where ... grades.date <= '1255503600' AND grades.date >= '984902400' 
group by     assignmentID order by grades.date DESC);

Eu acho que o problema é com a primeira tabela de classes ... o tipo ALL com que muitas linhas parece ser a causa .. Tudo é indexado.

I carregado a tabela como uma imagem. Não foi possível obter o direito formatação: http://imgur.com/AjX34.png

Um comentarista queria a cláusula completa, onde:

explain extended select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
where gradeID IN 
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC);
Foi útil?

Solução

Suponha que você use um banco de dados real (ou seja, qualquer banco de dados, exceto MySQL, mas eu vou usar Postgres como um exemplo) para fazer esta consulta:

SELECT * FROM ta WHERE aid IN (SELECT subquery)

um banco de dados real iria olhar para a subconsulta e estimar o seu número de linhas:

  • Se o número de linhas é pequeno (digamos, menos de alguns milhões)

Ele iria correr a subconsulta, em seguida, construir um hash na memória de IDs, o que também os torna únicos, o que é uma característica da IN ().

Então, se o número de linhas extraídos de ta é uma pequena parte da ta, seria usar um índice adequado para puxar as linhas. Ou, se uma parte importante da tabela é selecionada, seria apenas digitalizá-lo inteiramente, e pesquisar cada id no hash, que é muito rápido.

  • Se, contudo, o número de linhas subconsulta é bastante grande

O banco de dados provavelmente reescrevê-la como uma junção por mesclagem, adicionando um Sort + Exclusivo para a subconsulta.

No entanto, você está usando MySQL. Neste caso, ele não vai fazer nada disso (ele vai re-executar a subconsulta para cada linha da tabela) por isso vai levar 1000 anos. Desculpe.

Outras dicas

Consulte "A lentidão insuportável de IN": http://www.artfulsoftware.com/infotree/queries.php#568

Super confuso, mas: (obrigado pela ajuda de todos)

   SELECT * 
   FROM grades
   LEFT JOIN assignments ON grades.assignmentID = assignments.assignmentID
   RIGHT JOIN (

   SELECT g.gradeID
 FROM assignments a
 LEFT JOIN grades g
 USING ( assignmentID ) 
 WHERE a.classID =  '7815'
 AND (
 a.type =30170
 )
 AND g.contactID =7141
  g.points
 REGEXP  '^[-]?[0-9]+[-]?'
 AND g.points !=  '-'
 AND g.points !=  ''
 AND (
 g.pointsposs IS NULL 
 OR g.pointsposs =  ''
 )
 AND g.date <=  '1255503600'
 AND g.date >=  '984902400'
 GROUP BY assignmentID
 ORDER BY g.date DESC
 ) AS t1 ON t1.gradeID = grades.gradeID

Se o seu executa subconsulta bem quando ele é executado separadamente, em seguida, tente usar um JOIN em vez de, como este:

select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
join
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC) using (gradeID);

Há realmente não é informação suficiente para responder a sua pergunta, e você colocar um ... no meio da cláusula onde o que é estranho. Quão grande são as tabelas envolvidas e quais são os índices?

Dito isto, se há muitos termos em uma em cláusula, você pode ver o desempenho seriamente degradada. Substituir o uso de dentro com um certo juntar-se .

Para começar, a tabela as_types na na cláusula não é usado. Esquerda juntar não serve a nenhum propósito para se livrar dele.

que deixa o em cláusula de ter apenas a tabela de tarefas e notas da consulta externa. Claramente os wheres as atribuições Modificar pertencem na cláusula WHERE para a consulta externa. Você deve mover todos os que notas = whatever na cláusula ON da esquerda juntar-se aos graus.

A consulta é um pouco difícil de seguir, mas eu suspeito que a subconsulta não é necessário em tudo. Parece que sua consulta é basicamente assim:

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE gradeID IN 
(
SELECT grades.gradeID
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE your_conditions = TRUE
);

Mas, você não está fazendo nada muito chique na cláusula WHERE na subconsulta. Eu suspeito algo mais parecido

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
GROUP BY groupings
WHERE your_conditions_with_some_tweaks = TRUE;

iria funcionar tão bem.

Se eu estou faltando alguma lógica chave aqui por favor comentário de volta e eu vou editar / apagar esta mensagem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top