Pergunta

Estou usando o Toad do Quest para SQL Server em um servidor SQL Server 2000.

Aqui está minha consulta:

SELECT CASE SLCE.GroupName WHEN 'Other' THEN ARM.FBCOMPANY 
                           WHEN 'Inter Co.' THEN ARM.FBCOMPANY 
                           ELSE SLCE.GroupName END AS [Company Name], 
       ARM.fcustno AS [Cust No], 
       ARM.fbcompany AS [Cust Name], 
       ARM.fcinvoice AS [Invoice No], 
       ARM.fdgldate AS [Post Date], 
       year(arm.fdgldate) AS [Year Posted], 
       CASE ARM.fcsource WHEN 'S' THEN 'Shipper' 
                         WHEN 'O' THEN 'Sales Order' 
                         WHEN 'R' THEN 'Receiver' 
                         WHEN 'C' THEN 'Customer' 
                         ELSE ARM.fcsource END AS [Source Doc Type], 
       CASE ARM.fcstatus WHEN 'N' THEN 'New' 
                         WHEN 'U' THEN 'Unpaid' 
                         WHEN 'P' THEN 'Partially Paid' 
                         WHEN 'F' THEN 'Paid in Full' 
                         WHEN 'H' THEN 'Held' 
                         WHEN 'V' THEN 'Voided' 
                         ELSE ARM.fcstatus END AS [Invoice Status], 
       ARM.fpono AS [Cust PO No], 
       ARM.fsalespn AS [Sales Person], 
       ARI.fitem AS [Item No], 
       ARI.fprodcl AS [Prod Class], 
       ARI.fshipkey AS [Qty Invoiced], 
       ARI.ftotprice AS [Net Invoiced], 
       ARI.fpartno AS [Part No], 
       ARI.frev AS [Part Rev], 
       cast(ARI.fmdescript AS VARCHAR(20)) AS [Part Description], 
       ARM.fsono AS [Sales No], 
       ARI.fsokey AS [SO Rels Key], 
       ARI.fordqty AS [Qty Ordered], 
       RED.[YEAR] AS [Year], 
       RED.PERIOD AS [RF Period] 
  FROM dbo.armast ARM 
       INNER JOIN dbo.aritem ARI 
          ON ARM.FCINVOICE = ARI.FCINVOICE 
       INNER JOIN slcdpm SLC 
          ON SLC.fcustno = ARM.fcustno 
       LEFT OUTER JOIN slcdpm_ext SLCE 
         ON SLC.identity_column = SLCE.fkey_id 
       INNER JOIN REDFRIDAYDATES..TBLREDFRIDAYALLDATES RED 
          ON RED.date = CAST (FLOOR (CAST (ARM.fdgldate AS FLOAT)) AS DATETIME) 
 WHERE ARM.fcstatus <> 'V' 
   AND RED.[YEAR] = year(getdate()) 
   AND ari.frev = 'REP' 
   AND ARI.fsalesacc IN ('4010001', '4010002', '4010003', '4010004', '4010005', '4010006', '4010007', '4010008', '4010009', '4010010', '4010018', '4010019', '4010020', '4010021', '4010031', '4010050', '4022000', '4031000', '4045000', '4055000', '4057000', '4060000', '4070000')

Aqui está a opção de Toad (com diferenças destacadas) é:

INNER JOIN dbo.aritem ARI 
          ON ARM.FCINVOICE = ***COALESCE (ARI.FCINVOICE , ARI.FCINVOICE)*** 
       INNER JOIN slcdpm SLC 
          ON SLC.fcustno = ARM.fcustno 
       LEFT OUTER JOIN slcdpm_ext SLCE 
         ON SLC.identity_column = SLCE.fkey_id 
       INNER JOIN REDFRIDAYDATES..TBLREDFRIDAYALLDATES RED 
          ON RED.date = CAST (FLOOR (CAST (ARM.fdgldate AS FLOAT)) AS DATETIME) 
 WHERE ARM.fcstatus <> 'V' 
   AND RED.[YEAR] = year(getdate()) 
   AND ari.frev = 'REP' 
   AND ARI.fsalesacc IN ('4010001', '4010002', '4010003', '4010004', '4010005', '4010006', '4010007', '4010008', '4010009', '4010010', '4010018', '4010019', '4010020', '4010021', '4010031', '4010050', '4022000', '4031000', '4045000', '4055000', '4057000', '4060000', '4070000') 
   ***AND ARI.[fpartno] >= CHAR(0)***

Alguém pode me dizer por que isso Coalesce e adicional e a declaração aceleram esta consulta em mais de 50%?

Foi útil?

Solução

Você já deu uma olhada nos planos de execução reais. Isso deve mostrar as diferentes abordagens que o SQL Server adotou na execução dessas consultas.

Outras dicas

É definitivamente estranho. O plano de execução deve dizer com certeza, mas as alterações de desempenho como essa nos bancos de dados quase sempre se resumem a um índice. Portanto, meu melhor palpite é que, de alguma forma, o SQL Server estava faltando um índice que poderia usar e adicionar essas alterações estranhas fez com que se destacasse melhor.

Mas se você deseja aprender o 'por que' envolvido, para que da próxima vez pudesse escrever sua consulta para ser mais rápido, não há realmente nada lá.

Uma WAG completa:

Vou adivinhar que o FPartno tem uma condição "não nula" (para que o filtro adicionado sempre passa) e que o Toad sabe que o SQLServer não é inteligente o suficiente para detectar que> = char (0) é sempre verdadeiro. Portanto, isso sugere que o Toad está tentando orientar, de uma maneira muito oblíqua, o otimizador para usar algo que tenha o FPARTNO nele. Que algo poderia ser um índice composto (fcinvoice, fpartno) .. você tem um desses?

Como os outros disseram, o plano de explicação deve ser útil para explicar o mistério.

Nenhuma dessas mudanças tem efeito no significado lógico da consulta (ou seja, elas são "sem ops")

O único efeito físico que a Coalesce na cláusula ON seria impedir que o otimizador tentasse usar um índice para Ari.fcinvoice.

Da mesma forma, o único efeito físico que o "> = char (0)" poderia ter no otimizador poderia Seja para considerar o uso de uma varredura de intervalo indexada (ou também uma busca) em um índice que tinha Ari. [FPartno].

Portanto, minha conclusão seria que Toad está tentando manipular o otimizador para usar um índice específico sem realmente forçando Para usar esse índice com uma dica explícita. Na verdade, isso é meio inteligente, pois o problema real com as dicas do otimizador T-SQL são suas dependências e fragilidade.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top