A ordem das cláusulas where é importante no SQL?


121

Digamos que eu tenho uma tabela chamada PEOPLEcom 3 colunas ID, LastName, FirstName, nenhuma dessas colunas é indexada.
LastNameé mais exclusivo e FirstNameé menos exclusivo.

Se eu fizer duas pesquisas:

select * from PEOPLE where FirstName="F" and LastName="L" 
select * from PEOPLE where LastName="L" and FirstName="F"

Minha opinião é que o segundo é mais rápido, porque o critério mais exclusivo ( LastName) vem em primeiro lugar na wherecláusula e os registros serão eliminados com mais eficiência. Eu não acho que o otimizador seja inteligente o suficiente para otimizar o primeiro sql.

Meu entendimento está correto?


8
Não, essa ordem não importa - qualquer otimizador de consulta decente vai olhar para tudo o WHERE e descobrir a forma mais eficiente para satisfazer essa consulta
marc_s

3
Quais foram suas observações quando você executou essas duas declarações? Como eram os planos de execução?
Conrad Frix

3
Você está se referindo a um RDBMS específico? De fato, existem diferenças.
Bjoern


Respostas:


101

Não, essa ordem não importa (ou pelo menos: não deveria importar).

Qualquer otimizador de consulta decente examinará todas as partes da WHEREcláusula e descobrirá a maneira mais eficiente de satisfazer essa consulta.

Sei que o otimizador de consultas do SQL Server selecionará um índice adequado - não importa em que ordem você tenha suas duas condições. Presumo que outros RDBMS tenham estratégias semelhantes.

O que importa é se você possui ou não um índice adequado para isso!

No caso do SQL Server, ele provavelmente usará um índice se você tiver:

  • um índice em (LastName, FirstName)
  • um índice em (FirstName, LastName)
  • um índice em apenas (LastName), ou apenas (FirstName)(ou ambos)

Por outro lado - mais uma vez para o SQL Server - se você usa SELECT *para agarrar todas as colunas de uma tabela, ea tabela é bastante pequena, então há uma boa chance do otimizador de consulta vai fazer apenas uma tabela (ou índice de cluster) scan em vez de usar um índice (porque a pesquisa na página de dados completa para obter todas as outras colunas fica muito cara muito rapidamente).


Se não houver um índice, a operação pode estar correta, dependendo dos dados. Curso fazendo somnething como este sem índices, seria uma decisão estranha ...
Tony Hopkinson

@ TonyHopkinson: Acho que não - mesmo sem índices, duvido que exista alguma diferença. Afinal: sem índices, o que mais, além de uma verificação completa da tabela, o RDBMS pode fazer?
marc_s

2
Nota interessante com o servidor SQL, aparentemente, a fim de não existe dentro de predicados pode realmente influenciar criação do plano: bradsruminations.blogspot.com/2010/04/looking-under-hood.html
Justin Swartsel

3
O estranho é que, para a primeira execução de uma consulta, a ordem das condições na cláusula WHERE IMPORTA! Eu tinha duas condições, algo como: WHERE T1.col_1/T2.col_2 > 10 AND T2.col_2 <> 0e recebi um DIVIDE BY 0erro. Depois que eu mudei a ordem, as condições em que a consulta foi executada com êxito. Então, troquei a ordem de volta para que eu esperasse receber o erro novamente, mas desta vez funcionou! No final, minha conclusão foi que, para a primeira execução, a ordem importa, até que o plano de execução seja construído. 'assunto t porque o plano otimizador / exec vai cuidar dele
Radu Gheorghiu

1
Gosto que você disse: "... ou pelo menos: não deveria importar" - concordo totalmente. Às vezes isso importa, infelizmente. Eu já vi casos em que o SQL era muito complexo para o otimizador manipular, e coisas como ordem de coluna e ordem de junção de tabela fizeram diferença. Depende do RDBMS, da complexidade da instrução SQL e até do lançamento. SQL muito complexo pode resultar em decisões incorretas do otimizador ou no uso de padrões codificados no código do otimizador.
Victor Di Leo

19

A ordem das cláusulas WHERE não deve fazer diferença em um banco de dados que esteja em conformidade com o padrão SQL. A ordem da avaliação não é garantida na maioria dos bancos de dados.

Não pense que o SQL se preocupa com o pedido. A seguir, gera um erro no SQL Server:

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

Se a primeira parte desta cláusula fosse executada primeiro, apenas os nomes de tabelas numéricas seriam convertidos como números inteiros. No entanto, ele falha, fornecendo um exemplo claro de que o SQL Server (como em outros bancos de dados) não se importa com a ordem das cláusulas na instrução WHERE.


O que essa consulta que causa um erro tem a ver com a ordem da avaliação do predicado WHERE?
11117 Jim

7
@Jim If ISNUMERIC(table_name) = 1 fosse avaliado primeiro, CASTsó seria chamado para nomes de tabelas numéricas. Mas, como não é avaliado primeiro, também CASTé avaliado por nomes de tabela não numéricos, causando a mensagem de erro.
Hibbelig

2
Excelente esclarecimento
neeohw

Apenas para ter certeza de que verifiquei se a troca das condições faria com que o SQL Server as tratasse de maneira inversa, mas falha nos dois sentidos. Eu acho que isso pode significar uma de duas coisas: (1) não está otimizando tão bem quanto poderia ou (2) é um erro em tempo de compilação e o SQL nem começa a tentar comparar nada, ajudando preliminarmente. Meu palpite é que é nr. 2.
Louis Somers

9

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3 Ordem de avaliação da regra

...

Onde a precedência não é determinada pelos Formatos ou por parênteses, geralmente é realizada uma avaliação eficaz das expressões da esquerda para a direita. No entanto, depende da implementação se as expressões são realmente avaliadas da esquerda para a direita, principalmente quando operandos ou operadores podem causar condições a serem geradas ou se os resultados das expressões podem ser determinados sem avaliar completamente todas as partes da expressão.

copiado daqui


2

Não, todos os RDBMs começam primeiro analisando a consulta e otimizando-a reordenando sua cláusula where.

Dependendo de qual RDBM você estiver usando, é possível exibir qual é o resultado da análise (pesquise plano de explicação no oracle, por exemplo)

M.


Faz isso com base em índices. Portanto, é indireto em termos de conteúdo.
21412 Tony Hopkinson

1

Declaração OP original

Minha opinião é de que o segundo é mais rápido, porque o critério mais exclusivo (Sobrenome) vem em primeiro lugar na cláusula where, e os registros serão eliminados com mais eficiência. Eu não acho que o otimizador seja> inteligente o suficiente para otimizar o primeiro sql.

Eu acho que você está confundindo isso com a seleção da ordem das colunas enquanto cria os índices em que é necessário colocar as colunas mais seletivas primeiro que a segunda mais seletiva e assim por diante.

BTW, para as duas consultas acima, o otimizador do servidor SQL não fará nenhuma otimização, mas utilizará o plano Trivila desde que o custo total do plano seja menor que o custo limite do paralelismo.


0

É verdade, na medida do possível, assumindo que os nomes não estejam indexados. Dados diferentes tornariam errado, no entanto. Para descobrir qual a maneira de fazê-lo, o que poderia diferir sempre, o DBMS precisaria executar uma consulta de contagem distinta para cada coluna e comparar os números, o que custaria mais do que apenas dar de ombros e continuar com ele.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.