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...
Eu sei que isso pode depender de índices, mas, para esse propósito, digamos que não existem índices. O operador aritmético (+) tem um desempenho melhor que um operador lógico "OR" ou "AND"?
Estou com a impressão de que a adição tem um desempenho 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 em que 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 em que A <> 0 B <> 0 ou C <> 0 -> 3829750 Linhas 58 segundos
Retornando linhas em que F65 + F67 + f64 <> 0 -> 3829750 Linhas 57 segundos
Para a sala de cirurgia, parece que não há diferença significativa.
Eu concordo com o 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 assumir que pode 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 = Flutuar, B = Dinheiro e C = Flutuar. A consulta usada é como mostrado. No meu caso, todos são números positivos. Sem índices. É lógico em minha mente que a adição seria mais rápida que as condições lógicas!
fonte
Respostas:
Na sua pergunta, você detalha alguns testes que preparou onde "prova" que a opção de adição é mais rápida do que comparar as colunas discretas. Eu suspeito que sua metodologia de teste pode ter falhas de várias maneiras, como @gbn e @srutzky mencionaram.
Primeiro, você precisa garantir que não está testando o SQL Server Management Studio (ou qualquer outro cliente que esteja usando). Por exemplo, se você estiver executando um
SELECT *
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 como oSELECT COUNT(1)
que nega a necessidade de puxar milhões de linhas pela rede e renderizá-las na tela.Segundo, você precisa estar ciente do cache de dados do SQL Server. Normalmente, testamos a velocidade de leitura de dados do armazenamento e do processamento desses dados, a partir de um cache frio (por exemplo, os buffers do SQL Server estão vazios). Ocasionalmente, faz sentido fazer todos os seus testes com um cache quente, mas você precisa abordá-los 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 na sua pergunta, criei o seguinte banco de testes:
Isso retorna uma contagem de 260.144.641 na minha máquina.
Para testar o método "adição", eu corro:
A guia de mensagens mostra:
Para o teste "colunas discretas":
novamente, na guia Mensagens:
Nas estatísticas acima, você pode ver a segunda variante, com as colunas discretas comparadas com 0, o tempo decorrido é cerca de 10 segundos mais curto e o tempo da CPU é cerca de 6 vezes menor. As longas durações nos meus testes acima são principalmente o resultado da leitura de muitas linhas do disco. Se você reduzir o número de linhas para 3 milhões, verá que as proporções permanecem 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 "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 executar uma verificação de todo o índice:
e o método "colunas discretas", que pode procurar a primeira linha do índice em que a coluna principal do índice
A
é zero:fonte
Digamos que você tenha um índice em A, B, C e D. Também pode ser filtrado.
É mais provável que você use o índice do que a adição.
Em outras notícias, se A é -1 e B é 1,
A+B=0
é verdade, masA=0 and B=0
é falsa.fonte
(Observe que esta resposta foi enviada antes de qualquer teste ser observado na pergunta: o texto da pergunta terminou logo acima da seção de resultados do teste .)
Eu acho que as
AND
condições separadas seriam preferidas, já que o otimizador teria mais probabilidade de causar um curto-circuito na operação se um único deles não fosse igual a 0, sem a necessidade de fazer um cálculo primeiro.Ainda assim, como se trata de uma questão de desempenho, você deve primeiro configurar um teste para determinar a resposta no seu hardware. Relate esses resultados, mostrando seu código de teste e solicite que outras pessoas o examinem para garantir que foi um bom teste. Pode haver outros fatores dignos de consideração nos quais você não pensou.
fonte
Algum raciocínio geral: se você não possui nenhum índice em mãos, acho que não importará muito qual das duas soluções que você escolher, ambas terão um desempenho ruim. Se, por outro lado, você tiver um índice em uma ou mais das colunas do predicado, a primeira provavelmente terá um desempenho melhor que a segunda, pois a segunda provavelmente não poderá utilizar o (s) índice (s).
Disjunções (OR) em geral têm desempenho pior que conjunções (AND), mas mesmo se você tiver uma consulta com disjunções, colocarei meu dinheiro na primeira.
fonte
Não não é. Essa (tipo de) pergunta é o que atormenta muitos DBAs e desenvolvedores de software todos os dias, e é praticamente trivial.
Sim, você não vai. Pelo menos não uma resposta geral. Primeiro de tudo, isso dependerá enormemente 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 a seguinte.
Então, pode depender de qualquer quantidade de outros pequenos detalhes, por exemplo, como o seu banco de dados armazena os dados, se você tiver sub-seleções / junções que confundem o problema do otimizador de plano etc. O otimizador pode fornecer planos de execução diferentes, dependendo em quantas linhas você tem ...
Fazer um teste no mundo real geralmente é a única maneira útil de resolver perguntas como essa. Além disso, todos os ganhos obtidos por otimizações "misteriosas" como essa geralmente são ingeridos dez vezes por uma escolha inteligente de índices; portanto, eu não me incomodaria em gastar muito tempo com isso antes que um uso de índices seja realmente descartado.
fonte
Isso pode ser óbvio, mas se as colunas forem
INT
, entãoa+b+c
poderá ser igual a zero, mesmo quando nenhuma delas for zero. Você está testando duas coisas diferentes!fonte