Pergunta

Eu preciso de conselhos em relação ao desempenho subselect em MySQL. Por uma razão que eu não posso mudar, eu não sou capaz de uso Cadastre-se para criar quesry filtro, só posso adicionar outro E cláusula WHERE.

O que é a peformance de:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

em comparação com:

select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Note-se que há relativamente pequeno número de projectos whete is_template = 1, e pode haver grande número de projectos onde is_template <> 1.

Existe outra forma de conseguir o mesmo resultado sem subselects se eu não posso mudar nada, mas e filtro?

Foi útil?

Solução

Eu acredito que o segundo é mais eficiente, pois requer apenas um select, mas para ter certeza, você deve explicar cada consulta e verificar os resultados.

EXPLAIN select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

EXPLAIN select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Outras dicas

Quanto diferença que existe entre os dois poderia depender muito do que "alguns critérios" é e quais as oportunidades de usar índices que ele proporciona. Mas note que eles não são equivalentes em termos de resultados, se há tarefas que não têm projetos. O segundo é equivalente a esta:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id in (select id from project where project.is_template <> 1);

Eu acho que o primeiro pode dimensionar melhor:

Quando você faz uma junção, internamente mysql faz uma espécie de tabela temporária que consiste nas duas tabelas unidas de acordo com as condições de junção especificadas. Você não está dando uma condição de junção, por isso vai criar uma tabela temporária com todas as tarefas listadas contra todos os projetos. Estou bastante certo (mas verifique com a ferramenta explicar) que ele faz isso antes de aplicar quaisquer cláusulas where.

Resultado: se houver 10 de cada um, ele vai ter 10 * 10 linhas = 100. Você pode ver como isso se torna grande como números de subir. Em seguida, aplica a onde esta tabela temporária.

Por outro lado, os seleciona subconsulta somente as linhas relevantes de cada tabela.

Mas a menos de escala é uma preocupação, eu não acho que realmente importa.

Evite sub consultas como a praga em versões do MySQL <6,0, e eu duvido que você estiver usando 6.0, considerando que ainda está em fase alpha de desenvolvimento. AFAIK, o MySQL otimizador não lidar com subqueries bem em tudo. Alguns dos principais trabalho tem ido para renovar o otimizador para 6.0 e sub consultas estão trabalhando muito melhor agora, mas essas alterações não escorreu para as séries 5.0 ou 5.1.

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