Bom, Ruim ou Indiferente: ONDE 1 = 1

14

Dada essa pergunta no reddit, limpei a consulta para apontar onde estava o problema na consulta. Uso vírgula primeiro e WHERE 1=1para facilitar a modificação de consultas, de modo que minhas consultas geralmente acabam assim:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Alguém basicamente disse que 1 = 1 geralmente é preguiçoso e ruim para o desempenho .

Como não quero "otimizar prematuramente" - quero seguir boas práticas. Analisei os planos de consulta antes, mas geralmente apenas para descobrir quais índices posso adicionar (ou ajustar) para fazer com que minhas consultas sejam executadas mais rapidamente.

A questão então realmente ... faz Where 1=1com que coisas ruins aconteçam? E se sim, como posso saber?

Edição menor: Eu sempre 'assumi' que 1=1seria otimizado ou, na pior das hipóteses, seria insignificante. Nunca é demais questionar um mantra, como "Goto é mau" ou "Otimização prematura ..." ou outros fatos assumidos. Não tinha certeza se 1=1 ANDisso afetaria realisticamente os planos de consulta ou não. E nas subconsultas? CTE's? Procedimentos?

Não sou de otimizar, a menos que seja necessário ... mas se estou fazendo algo que é realmente "ruim", gostaria de minimizar os efeitos ou alterar, quando aplicável.

WernerCD
fonte
2
Não, não seria. Além de alguns microssegundos, o otimizador remove a condição redundante. É melhor você se concentrar em seus literais de data não serem ambíguos.
precisa saber é o seguinte
Como o @ypercube disse, não faz diferença. O otimizador de consulta teria que ser um pedaço de **** para tal coisa a fazer qualquer diferença;)
Philᵀᴹ
4
Não acredite em tudo que lê no reddit. Por favor.
Aaron Bertrand
1
@AaronBertrand Eu tomo tudo com um grão de sal, até experimentar em primeira mão. Ainda vou fazer uma pergunta que parece plausível e ver se existe alguma verdade, especialmente quando isso afeta o meu trabalho do dia a dia.
WernerCD
4
Há grãos de sal, então não há o teor de sal de um oceano inteiro despejado no topo do seu edifício de escritórios: P
Philᵀᴹ

Respostas:

13

O SQL Server analisadorO otimizador possui um recurso chamado "Dobragem constante" que elimina expressões tautológicas da consulta.
Se você observar o plano de execução, em nenhum lugar dos predicados verá a expressão aparecer. Isso implica que a dobragem constante é realizada de qualquer maneira no tempo de compilação por esse e outros motivos e não afeta o desempenho da consulta.

Consulte Avaliação constante das expressões e dobras durante a estimativa de cardinalidade para obter mais informações.

spaghettidba
fonte
Provavelmente, ele foi compilado porque esse é um padrão conhecido para concatenação de campos.
Jcolebrand
Não, é compilado porque é tautológico. Funcionaria da mesma maneira com 2736 = 2736, que não é tão usual quanto 1 = 1. O mesmo se aplica às contradições. Nesse caso, o recurso é chamado "Detecção de contradição".
Spaghettidba
Qual parte do "padrão conhecido" significava "tem que ser 1 = 1"?
Jcolebrand
9

A adição do predicado redundante pode fazer a diferença no SQL Server.

Nos planos de execução abaixo, observe o @1no primeiro plano versus o literal 'foo'no segundo plano.

insira a descrição da imagem aqui

Isso indica que o SQL Server considerou a primeira consulta para parametrização simples para promover a reutilização do plano de execução - no entanto, a comparação de duas constantes impede que isso aconteça no segundo caso.

Uma lista de condições que impedem a parametrização simples (anteriormente conhecida como parametrização automática) pode ser encontrada no Apêndice A dos Documentos Técnicos da Microsoft de Cache do Plano:

parametrização simples geralmente não é algo em que você deva confiar, de qualquer maneira. É muito melhor parametrizar explicitamente suas consultas.

Martin Smith
fonte
4

Em qualquer RDBMS moderno (incluindo Oracle, Microsoft SQL Server e PostgreSQL - tenho certeza sobre isso), isso não afetará o desempenho.

Como alguém observou, isso afetará apenas a fase de planejamento da consulta. Portanto, a diferença será visível apenas quando você executar milhares de iterações de uma consulta simplista que não retorna nenhum dado, como este:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Para mim, no PostgreSQL 9.0, isso é visível com apenas 10000 iterações:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms
filiprem
fonte
0

Isso pode ser "problema" para o Oracle quando você usa o parâmetro cursor_sharing do banco de dados. Quando definido como "force", ele modifica todas as instruções SQL. Todas as "constantes" nas consultas serão substituídas por variáveis ​​de ligação (como 1 =>: SYS_0).

Esta opção foi introduzida para lidar com alguns desenvolvedores preguiçosos. Por outro lado, também pode prejudicar outros desenvolvedores preguiçosos. Mas o risco não é muito alto. Desde o 11g, ele tem o recurso de espreitar variável.

ibre5041
fonte
Você pode esclarecer o que "Desde o 11g, ele tem o recurso de espreitar variáveis". significa?
precisa saber é o seguinte
@ypercube "Espreitar a variável de ligação" significa que o otimizador observará os valores reais das variáveis ​​de ligação e usará as estatísticas de dados para reavaliar e possivelmente regenerar o plano de execução da consulta. Duvido que espiar terá algum efeito sobre a construção que está sendo discutida, pois não depende de estatísticas de dados.
mustaccio