Sintaxe ANSI vs. ANSI SQL JOIN

Eu tenho minha lógica de negócios em ~ 7000 linhas de stored procedures T-SQL, e a maioria deles tem a próxima syntax JOIN:

SELECT AA, BB, CC FROM aaa AS A, bbb AS B, ccc AS C WHERE AB = B.ID AND BC = C.ID AND C.ID = @param 

Terei um crescimento de desempenho se eu replace essa consulta por isso:

 SELECT AA, BB, CC FROM aaa AS A JOIN bbb AS B ON AB = B.ID JOIN ccc AS C ON BC = C.ID AND C.ID = @param 

Ou eles são os mesmos?

As duas consultas são as mesmas, exceto a segunda é a syntax SQL ANSI-92 e a primeira é a syntax SQL mais antiga que não incorporou a cláusula join. Eles devem produzir exatamente o mesmo plano de consulta interna, embora você queira verificar.

Você deve usar a syntax ANSI-92 por vários motivos

  • O uso da cláusula JOIN separa a lógica de relacionamento da lógica de filtro (o WHERE) e é, portanto, mais limpa e fácil de entender.
  • Não importa com essa consulta específica, mas há algumas circunstâncias em que a syntax de junit externa mais antiga (usando +) é ambígua e os resultados da consulta são, portanto, dependentes da implementação – ou a consulta não pode ser resolvida de forma alguma. Estes não ocorrem com ANSI-92
  • É uma boa prática, já que a maioria dos desenvolvedores e dba’s usam o ANSI-92 hoje em dia e você deve seguir o padrão. Certamente todas as ferramentas de consulta modernas irão gerar o ANSI-92.
  • Como apontado por @gbn, ele tende a evitar junções cruzadas acidentais.

Eu resisti ao ANSI-92 por algum tempo, pois existe uma ligeira vantagem conceitual para a syntax antiga, já que é mais fácil visualizar o SQL como uma junit cartesiana de massa de todas as tabelas usadas, seguida por uma operação de filtragem – uma técnica mental que pode ser útil para entender o que uma consulta SQL está fazendo. No entanto, eu decidi há alguns anos que eu precisava me mexer com os tempos e depois de um período de adaptação relativamente curto, eu agora prefiro fortemente – predominantemente por causa da primeira razão dada acima. O único local em que alguém deve se afastar da syntax ANSI-92, ou melhor, não usar a opção, é com junções naturais que são implicitamente perigosas.

A segunda construção é conhecida como “syntax de junit infixada” na comunidade SQL. A primeira construção AFAIK não tem nome amplamente aceito, então vamos chamá-la de syntax de junit interna de ‘estilo antigo’.

Os argumentos usuais são assim:

Prós da syntax ‘Tradicional’: os predicados são fisicamente agrupados na cláusula WHERE na ordem que faz a consulta em geral, e as relações n-árias particularmente, mais fáceis de ler e entender (as cláusulas ON da syntax infixada podem se espalhar os predicados, então você deve procurar a aparência de uma tabela ou coluna em uma distância visual).

Desvantagens da syntax ‘Tradicional’: Não há erro de análise ao omitir um dos predicados ‘join’ e o resultado é um produto cartesiano (conhecido como CROSS JOIN na syntax infixada) e tal erro pode ser difícil de detectar e depurar. Além disso, os predicados ‘join’ e os predicados ‘filtering’ são fisicamente agrupados na cláusula WHERE , o que pode causar confusão entre eles.

Execute ambos e verifique seus planos de consulta. Eles devem ser iguais.

As duas consultas são iguais – a primeira é a syntax não-ANSI JOIN, a segunda é a syntax ANSI JOIN. Eu recomendo ficar com a syntax ANSI JOIN.

E sim, LEFT OUTER JOINs (que, aliás, também são syntax ANSI JOIN) são o que você deseja usar quando existe a possibilidade de que a tabela à qual você está ingressando não contenha registros correspondentes.

Referência: associações condicionais no SQL Server

OK, eles executam o mesmo. Isso está de acordo. Ao contrário de muitos, eu uso a convenção mais antiga. Que o SQL-92 seja “mais fácil de entender” é discutível. Tendo escrito linguagens de programação para empurrar 40 anos (gole) eu sei que ‘fácil de ler’ começa primeiro, antes de qualquer outra convenção, com ‘acuidade visual’ (termo mal aplicado aqui, mas é a melhor frase que posso usar). Ao ler o SQL, a PRIMEIRA coisa em que você se importa é quais tabelas estão envolvidas e, em seguida, qual tabela (a maioria) define o grão. Então você se preocupa com as restrições relevantes nos dados e, em seguida, com os atributos selecionados. Enquanto o SQL-92 principalmente separa essas idéias, há tantas palavras de ruído, que o olho da mente tem que interpretar e lidar com elas e faz a leitura do SQL mais lenta.

 SELECT Mgt.attrib_a AS attrib_a ,Sta.attrib_b AS attrib_b ,Stb.attrib_c AS attrib_c FROM Main_Grain_Table Mgt ,Surrounding_TabA Sta ,Surrounding_tabB Stb WHERE Mgt.sta_join_col = Sta.sta_join_col AND Mgt.stb_join_col = Stb.stb_join_col AND Mgt.bus_logic_col = 'TIGHT' 

Acuidade Visual! Coloque as vírgulas para novos atributos na frente Facilita o código de comentários Use um caso específico para funções e palavras-chave Use um caso específico para tabelas Use um caso específico para atributos Operadores e operações na vertical Alinhe a (s) primeira (s) tabela (s) representar o grão dos dados Faça com que as primeiras tabelas do WHERE sejam associadas a restrições e deixe que as restrições específicas e restritas flutuem até o fundo. Selecione o alias de 3 caracteres para TODAS as tabelas em seu database e use o alias em TODOS os pontos de referência da tabela. Você deve usar esse alias como um prefixo para (muitos) índices nessa tabela também. 6 de 1 1/2 dúzia de outro, certo? Talvez. Mas mesmo se você estiver usando a convenção ANSI-92 (como eu tenho e em casos continuarão a fazer) use princípios de acuidade visual, alinhamento de verticais para permitir que sua mente desvie para os lugares que você quer ver e evite coisas facilmente palavras de ruído) você não precisa.

Na minha opinião, a cláusula FROM é onde eu decido quais colunas eu preciso nas linhas para a minha cláusula SELECT trabalhar. É onde uma regra de negócios é expressa que trará para a mesma linha os valores necessários nos cálculos. A regra de negócios pode ser clientes que possuem faturas, resultando em linhas de faturas, incluindo o cliente responsável. Também podem ser locais no mesmo código postal que os clientes, resultando em uma lista de locais e clientes que estão próximos.

É onde eu trabalho a centricidade das linhas no meu conjunto de resultados. Afinal de contas, simplesmente mostramos a metáfora de uma lista em RDBMSs, cada lista tendo um tópico (a entidade) e cada linha sendo uma instância da entidade. Se a centricidade de linha é entendida, a entidade do conjunto de resultados é compreendida.

A cláusula WHERE, que conceitualmente é executada depois que as linhas são definidas na cláusula from, seleciona linhas não necessárias (ou inclui linhas que são necessárias) para que a cláusula SELECT trabalhe.

Como a lógica de junit pode ser expressa tanto na cláusula FROM como na cláusula WHERE, e porque as cláusulas existem para dividir e conquistar a lógica complexa, eu escolho colocar a lógica de junit que envolve valores em colunas na cláusula FROM porque isso é essencialmente expressar um negócio regra que é suportada pelos valores correspondentes nas colunas.

ou seja, não vou escrever uma cláusula WHERE como esta:

  WHERE Column1 = Column2 

Vou colocar isso na cláusula FROM assim:

  ON Column1 = Column2 

Da mesma forma, se uma coluna tiver que ser comparada a valores externos (valores que podem ou não estar em uma coluna), como comparar um CEP a um CEP específico, eu colocarei isso na cláusula WHERE, porque estou essencialmente dizendo que só quero linhas como esta.

ou seja, não vou escrever uma cláusula FROM como esta:

  ON PostCode = '1234' 

Vou colocar isso na cláusula WHERE assim:

  WHERE PostCode = '1234' 

A syntax ANSI não impõe a colocação de predicado na cláusula correta (seja ON ou WHERE), nem a afinidade da cláusula ON à referência de tabela adjacente. Um desenvolvedor é livre para escrever uma bagunça como essa

 SELECT C.FullName, C.CustomerCode, O.OrderDate, O.OrderTotal, OD.ExtendedShippingNotes FROM Customer C CROSS JOIN Order O INNER JOIN OrderDetail OD ON C.CustomerID = O.CustomerID AND C.CustomerStatus = 'Preferred' AND O.OrderTotal > 1000.0 WHERE O.OrderID = OD.OrderID; 

Falando de ferramentas de consulta que “irão gerar ANSI-92”, estou comentando aqui porque gerou

 SELECT 1 FROM DEPARTMENTS C JOIN EMPLOYEES A JOIN JOBS B ON C.DEPARTMENT_ID = A.DEPARTMENT_ID ON A.JOB_ID = B.JOB_ID 

A única syntax que escapa do “produto cartesiano de projeto restrito” convencional é a junit externa. Essa operação é mais complicada porque não é associativa (com ela mesma e com junit normal). Um tem que criteriosamente paretizar a consulta com outer join, pelo menos. No entanto, é uma operação exótica; Se você estiver usando isso com muita frequência, sugiro usar a class de database relacional.

Intereting Posts