Esta é uma pergunta simples para a qual não consigo encontrar a resposta.
Em termos de desempenho, se eu tiver uma WHERE
cláusula como a=0 and b=0 and ... z=0
, eu obteria algum desempenho se substituísse essa condição por a+b+...+z=0
?
Em outras palavras, há algum ganho de desempenho substituindo o seguinte
Select *
From MyTable
Where A=0 and B=0 and C=0 and D=0...
Com
Select *
From MyTable
Where A+B+C+D=0...
Sei que pode depender de índices, mas, para esse fim, digamos que não existam índices. O operador aritmético (+) funciona melhor que um operador lógico "OU" ou "E"?
Tenho a impressão de que a adição funciona melhor do que várias condições com ANDs ou ORs.
Resultado dos testes
Em uma tabela de 4,2 milhões de linhas
Retornando linhas Onde A=0 B=0 e C=0 -> 351748 Linhas
A adição (A+B+C=0) levou 5 segundos, enquanto as condições lógicas A=0 e B=0 e C=0 levaram 11 segundos.
Por outro lado
Retornando linhas Onde A<>0 B<>0 ou C<>0 -> 3829750 Linhas 58 segundos
Retornando linhas Onde F65+ F67+f64<>0 -> 3829750 Linhas 57 segundos
Para o OR, parece que não há diferença significativa.
Concordo com gbn:
Se A é -1 e B é 1, A+B=0 mas A=0 e B= 0 é falso
e com AMtwo:
ABS(A)+ABS(B)+ABS(C)+ABS(D)... Mesmo que você espere apenas valores positivos, se a coluna aceitar valores negativos, você deve presumir que poderá encontrar um
Os resultados são muito impressionantes, como pensei, parece que a adição é muito mais rápida que os operadores lógicos.
A = Float, B = Dinheiro e C = Float. A consulta utilizada é a mostrada. No meu caso, todos são números positivos. Sem índices. É lógico em minha mente que a adição seja mais rápida do que as condições lógicas!
Na sua pergunta, você detalha alguns testes que preparou onde "comprova" que a opção de adição é mais rápida do que comparar as colunas discretas. Eu suspeito que sua metodologia de teste pode ser falha de várias maneiras.
Primeiro, você precisa garantir que não está testando o SQL Server Management Studio (ou qualquer cliente que esteja usando). Por exemplo, se você estiver executando um a
SELECT *
partir de uma tabela com 3 milhões de linhas, estará testando principalmente a capacidade do SSMS de extrair linhas do SQL Server e renderizá-las na tela. É muito melhor usar algo comoSELECT COUNT(1)
o que nega a necessidade de puxar milhões de linhas pela rede e renderizá-las na tela.Em segundo lugar, você precisa estar ciente do cache de dados do SQL Server. Normalmente, testamos a velocidade de leitura de dados do armazenamento e processamento desses dados de um cache frio (ou seja, os buffers do SQL Server estão vazios). Ocasionalmente, faz sentido fazer todos os seus testes com um cache quente, mas você precisa abordar seus testes explicitamente com isso em mente.
Para um teste de cache frio, você precisa executar
CHECKPOINT
eDBCC DROPCLEANBUFFERS
antes de cada execução do teste.Para o teste que você perguntou em sua pergunta, criei o seguinte test-bed:
Isso retorna uma contagem de 260.144.641 em minha máquina.
Para testar o método "adição", eu executo:
A guia de mensagens mostra:
Para o teste de "colunas discretas":
novamente, na guia de mensagens:
Nas estatísticas acima, você pode ver a segunda variante, com as colunas discretas comparadas a 0, o tempo decorrido é cerca de 10 segundos mais curto e o tempo da CPU é cerca de 6 vezes menor. As longas durações em meus testes acima são principalmente resultado da leitura de muitas linhas do disco. Se você diminuir o número de linhas para 3 milhões, verá que as taxas permanecem praticamente as mesmas, mas os tempos decorridos caem visivelmente, pois a E/S do disco tem muito menos efeito.
Com o método "Adição":
Com o método "colunas discretas":
O que fará uma diferença realmente grande para este teste? Um índice apropriado, como:
O método de "adição":
O método "colunas discretas":
O plano de execução para cada consulta (com o índice acima no local) é bastante revelador.
O método "adição", que deve realizar uma varredura de todo o índice:
e o método "colunas discretas", que pode buscar a primeira linha do índice onde a coluna do índice principal,
A
, é zero:Digamos que você tenha um índice em A, B, C e D. Também pode ser filtrado.
É mais provável que use o índice do que a adição.
Em outras notícias, Se A for -1 e B for 1,
A+B=0
é verdadeiro, masA=0 and B=0
é falso.(Observe que esta resposta foi enviada antes de qualquer teste ser anotado na pergunta: o texto da pergunta terminava logo acima da seção de resultados do teste .)
Eu acho que as
AND
condições separadas seriam preferidas, pois o otimizador teria mais probabilidade de causar um curto-circuito na operação se uma única delas não fosse igual a 0, sem a necessidade de fazer um cálculo primeiro.Ainda assim, como esta é uma questão de desempenho, você deve primeiro configurar um teste para determinar a resposta em seu hardware. Relate esses resultados, mostrando seu código de teste e peça a outras pessoas que o examinem para ter certeza de que foi um bom teste. Pode haver outros fatores dignos de consideração nos quais você não pensou.
Algum raciocínio geral, se você não tiver nenhum índice em mãos, não acho que fará muita diferença qual das duas soluções você escolherá, ambas terão um desempenho ruim. Se, por outro lado, você tiver um índice em uma ou mais colunas no predicado, o primeiro provavelmente terá um desempenho melhor que o segundo, já que o segundo provavelmente não poderá utilizar o(s) índice(s).
As disjunções (OR) em geral têm um desempenho pior do que as conjunções (AND), mas mesmo que você tenha uma consulta com disjunções, apostarei na primeira.
Não não é. Esse (tipo de) pergunta é o que atormenta muitos DBAs e desenvolvedores de software todos os dias, e é quase trivial.
Sim, você não vai. Pelo menos não uma resposta geral. Em primeiro lugar, vai depender muito de qual RDBMS você está usando (OK, você está usando sql-server , mas ainda assim). Pode até mudar quando você passa de uma versão do seu RDBMS para outra.
Então, pode depender de qualquer quantidade de outros pequenos detalhes, por exemplo, como seu banco de dados armazena os dados, se você tem sub-seleções/junções que confundem o problema para o otimizador de plano, etc. O otimizador pode fornecer diferentes planos de execução, dependendo em quantas linhas você tem...
Fazer um teste do mundo real geralmente é a única maneira útil de resolver questões como essa. Além disso, quaisquer ganhos obtidos por otimizações "arcanas" como essa são geralmente engolidos dez vezes pela escolha inteligente de índices, então eu não me incomodaria em gastar muito tempo com isso, antes que o uso de índices fosse realmente descartado.