SQL (qualquer) Pedido de visão sobre a otimização de consultas
-
21-08-2019 - |
Pergunta
Eu tenho uma consulta particularmente lento devido à grande quantidade de informação a ser unidas. No entanto eu precisava para adicionar uma cláusula WHERE na forma de id in (SELECT id da tabela).
Eu quero saber se existe algum ganho a partir do seguinte, e mais urgente, vai mesmo dar os resultados desejados.
select a.* from a where a.id in (select id from b where b.id = a.id)
como uma alternativa para:
select a.* from a where a.id in (select id from b)
Update: MySQL não pode ser mais específico pena Tabela A é efetivamente uma junção entre 7 mesas diferentes. uso de * é para exemplos
Editar, b não selecionado
Solução
A sua pergunta foi sobre a diferença entre estes dois:
select a.* from a where a.id in (select id from b where b.id = a.id)
select a.* from a where a.id in (select id from b)
O primeiro é uma correlacionada subconsulta. Isso pode causar MySQL para executar a subconsulta para cada linha de a
.
O último é uma não-correlacionada subconsulta. MySQL deve ser capaz de executá-lo uma vez e armazenar em cache os resultados para comparação com cada linha de a
.
Gostaria de usar o último.
Outras dicas
Ambas as consultas que você lista são o equivalente a:
select a.*
from a
inner join b on b.id = a.id
Quase todos os otimizadores vai executá-las da mesma forma.
Você pode postar um plano de execução real, e alguém aqui pode dar-lhe uma maneira de acelerá-lo. Ela ajuda se você especificar o servidor de banco de dados você está usando.
YMMV, mas eu tenho encontrado frequentemente usando EXISTS em vez de faz consultas correr mais rápido.
SELECT a.* FROM a WHERE EXISTS (SELECT 1 FROM b WHERE b.id = a.id)
É claro que, sem ver o resto da consulta e do contexto, isso pode não fazer a consulta mais rápido.
junção pode ser uma opção mais preferível, mas se aparece a.id mais de uma vez na coluna ID de b, você teria que jogar um distinto lá, e você mais do que provável ir para trás em termos de otimização.
Eu nunca usaria uma subconsulta como esta. A juntar-se seria muito mais rápido.
select a.*
from a
join b on a.id = b.id
É claro que não usar select * ou (especialmente nunca usá-lo ao fazer uma junção de pelo menos um campo é repetido) e desperdiça recursos de rede para enviar dados unnneeded.
Você já olhou para o plano de execução?
Como cerca
select a.*
from a
inner join b
on a.id = b.id
presumivelmente os campos de identificação são as chaves primárias?
Select a.* from a
inner join (Select distinct id from b) c
on a.ID = c.AssetID
Eu tentei todas as 3 versões e eles correram sobre o mesmo. O plano de execução foi a mesma (junção interna, IN (com e sem cláusula WHERE na subconsulta), existe)
Desde que você não está selecionando quaisquer outros campos de B, eu prefiro usar a IN (Select ...) ninguém para onde iria olhar para a consulta e saber o que você está tentando fazer (mostrar Somente em um caso em b. ).
Seu problema é mais provável nos sete tabelas dentro "a"
fazer a FROM tabela conter o "a.id" fazer o próximo juntar-se: junção interna b em a.id = b.id
, em seguida, juntar-se outros seis mesas.
Você realmente precisa mostrar toda a consulta, a lista de todos os índices, e contagens de linha aproximados de cada tabela se você quiser ajuda real