Preciso escrever uma consulta para recuperar uma grande lista de IDs.
Nós suportamos muitos back-ends (MySQL, Firebird, SQLServer, Oracle, PostgreSQL ...), então eu preciso escrever um SQL padrão.
O tamanho do conjunto de IDs pode ser grande, a consulta será gerada programaticamente. Então, qual é a melhor abordagem?
1) Escrevendo uma consulta usando IN
SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)
Minha pergunta aqui é. O que acontece se n for muito grande? Além disso, e o desempenho?
2) Escrevendo uma consulta usando OR
SELECT * FROM TABLE WHERE ID = id1 OR ID = id2 OR ... OR ID = idn
Eu acho que essa abordagem não tem n limite, mas e quanto ao desempenho se n for muito grande?
3) Escrevendo uma solução programática:
foreach (var id in myIdList)
{
var item = GetItemByQuery("SELECT * FROM TABLE WHERE ID = " + id);
myObjectList.Add(item);
}
Tivemos alguns problemas com essa abordagem quando o servidor de banco de dados é consultado pela rede. Normalmente, é melhor fazer uma consulta que recupere todos os resultados do que fazer muitas consultas pequenas. Talvez eu esteja errado.
Qual seria a solução correta para esse problema?
IN
! Fiz o meu como sua solução 1 + 3. Apenas a consulta final foi uma, longa cadeia de caracteres de consulta enviada ao SQL para execução.Respostas:
A opção 1 é a única boa solução.
Por quê?
A opção 2 faz o mesmo, mas você repete o nome da coluna várias vezes; Além disso, o mecanismo SQL não sabe imediatamente que você deseja verificar se o valor é um dos valores em uma lista fixa. No entanto, um bom mecanismo SQL poderia otimizá-lo para ter um desempenho igual ao anterior
IN
. Ainda existe o problema de legibilidade ...A opção 3 é simplesmente horrível em termos de desempenho. Ele envia uma consulta a cada loop e martela o banco de dados com pequenas consultas. Também impede o uso de otimizações para "o valor é um daqueles em uma determinada lista"
fonte
Uma abordagem alternativa pode ser usar outra tabela para conter valores de ID. Essa outra tabela pode ser unida internamente em sua TABLE para restringir as linhas retornadas. Isso terá a grande vantagem de que você não precisará de SQL dinâmico (problemático na melhor das hipóteses) e não terá uma cláusula IN infinitamente longa.
Você truncaria essa outra tabela, insira seu grande número de linhas e, em seguida, talvez crie um índice para ajudar no desempenho da junção. Também permitiria desanexar o acúmulo dessas linhas da recuperação de dados, talvez oferecendo mais opções para ajustar o desempenho.
Atualização : Embora você possa usar uma tabela temporária, não pretendi sugerir que você deva ou deva. Uma tabela permanente usada para dados temporários é uma solução comum com méritos além do descrito aqui.
fonte
select
instrução em outra tabela. A lista é passada como a outra tabela em que você se encontrainner join
.O que Ed Guiness sugeriu é realmente um impulsionador de desempenho, eu tive uma consulta como esta
o que eu fiz :
Então o interior juntou-se ao temp com a tabela principal:
E o desempenho melhorou drasticamente.
fonte
A primeira opção é definitivamente a melhor opção.
No entanto, considerando que a lista de IDs é muito grande , digamos milhões, considere os tamanhos dos blocos, como abaixo:
Por que você deve se dividir em pedaços?
Sempre funcionou como charme para mim. Espero que funcione para os meus colegas desenvolvedores também :)
fonte
A execução do comando SELECT * FROM MyTable where id in () em uma tabela SQL do Azure com 500 milhões de registros resultou em um tempo de espera de> 7min!
Fazer isso retornou resultados imediatamente:
Use uma associação.
fonte
Na maioria dos sistemas de banco de dados,
IN (val1, val2, …)
e uma série deOR
são otimizados para o mesmo plano.A terceira maneira seria importar a lista de valores para uma tabela temporária e juntá-la, o que é mais eficiente na maioria dos sistemas, se houver muitos valores.
Você pode ler estes artigos:
fonte
A amostra 3 seria a pior de todas, porque você está acessando o banco de dados inúmeras vezes sem motivo aparente.
Carregar os dados em uma tabela temporária e depois ingressar nela seria de longe o mais rápido. Depois disso, o IN deve funcionar um pouco mais rápido que o grupo de ORs.
fonte
Eu acho que você quer dizer SqlServer, mas no Oracle você tem um limite rígido de quantos elementos IN você pode especificar: 1000.
fonte