consultar ganhos de desempenho removendo a combinação interna de hash do operador

9

Ao tentar aplicar o conteúdo desta pergunta abaixo à minha própria situação, estou um pouco confuso sobre como me livrar do operador Hash Match (Inner Join), se possível.

Desempenho de consulta do SQL Server - removendo a necessidade de Hash Match (Inner Join)

Percebi o custo de 10% e fiquei imaginando se poderia reduzi-lo. Veja o plano de consulta abaixo.

insira a descrição da imagem aqui

Este trabalho vem de uma consulta que eu tive que ajustar hoje:

SELECT c.AccountCode, MIN(d.CustomerSID) 
FROM   Stage.Customer c 
INNER JOIN Dimensions.Customer d  ON c.Email = d.Email
                                  OR (
                                          c.HomePostCode = d.HomePostCode
                                       AND c.StrSurname = d.strSurname
                                                                    )
GROUP BY c.AccountCode

e depois de adicionar estes índices:

---------------------------------------------------------------------
-- Create the indexes
---------------------------------------------------------------------

CREATE NONCLUSTERED INDEX IDX_Stage_Customer_HOME_SURNAME_INCL
ON Stage.Customer(HomePostCode ,strSurname)
INCLUDE (AccountCode)
--WHERE HASEMAIL = 0
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go


CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_HOME_SURNAME_INCL
ON Dimensions.Customer(HomePostCode ,strSurname)
INCLUDE (AccountCode,CustomerSID)
--WHERE HASEMAIL = 0
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go



CREATE NONCLUSTERED INDEX IDX_Stage_Customer_EMAIL_INCL
ON Stage.Customer(EMAIL)
INCLUDE (AccountCode)
--WHERE HASEMAIL = 1
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go


CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_EMAIL_INCL
ON Dimensions.Customer(EMAIL)
INCLUDE (AccountCode,CustomerSID)
--WHERE HASEMAIL = 1
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go

esta é a nova consulta:

----------------------------------------------------------------------------
-- new query 
----------------------------------------------------------------------------

SELECT * 
FROM (    
SELECT AccountCode
     ,RO=ROW_NUMBER () OVER (PARTITION BY AccountCode ORDER BY CustomerSID)
     --,CustomerSID=MIN(CustomerSID) OVER (PARTITION BY AccountCode ORDER BY AccountCode)
       ,CustomerSID
FROM (    
          SELECT c.AccountCode, D.CustomerSID
       FROM   Stage.Customer c 
       INNER JOIN Dimensions.Customer d  ON c.Email = d.Email

          UNION ALL

          SELECT c.AccountCode, D.CustomerSID
       FROM   Stage.Customer c 
       INNER JOIN Dimensions.Customer d  ON c.HomePostCode = d.HomePostCode
                                        AND c.StrSurname = d.strSurname
) RADHE
) R1
WHERE RO = 1

Isso reduziu o tempo de execução da consulta de 8 minutos para 1 segundo.

Todo mundo está feliz, mas ainda assim gostaria de saber se poderia fazer mais, ou seja, removendo de alguma forma o operador de combinação de hash.

Por que está lá em primeiro lugar, estou combinando todos os campos, por que hash?

Marcello Miorelli
fonte

Respostas:

14

os links a seguir fornecerão uma boa fonte de conhecimento sobre os planos de execução.

Dos princípios básicos do plano de execução - confusão de correspondência de hash, descobri:

De http://sqlinthewild.co.za/index.php/2007/12/30/execution-plan-operations-joins/

"A junção de hash é uma das operações de junção mais caras, pois requer a criação de uma tabela de hash para fazer a junção. Dito isso, é a junção que é melhor para entradas grandes e não classificadas. É a que mais consome muita memória. das junções

A junção de hash lê primeiro uma das entradas e hashes da coluna de junção e coloca os valores de hash e coluna resultantes em uma tabela de hash criada na memória. Em seguida, ele lê todas as linhas da segunda entrada, faz o hash e verifica as linhas no intervalo de hash resultante para as linhas de junção ".

quais links para este post:

http://blogs.msdn.com/b/craigfr/archive/2006/08/10/687630.aspx

Você pode explicar esse plano de execução? fornece boas informações sobre o plano de execução, não específicas à correspondência de hash, mas relevantes.

As varreduras constantes são uma maneira de o SQL Server criar um bucket no qual colocará algo posteriormente no plano de execução. Eu postei uma explicação mais completa sobre isso aqui . Para entender para que serve a varredura constante, é necessário examinar mais detalhadamente o plano. Nesse caso, são os operadores Escalar de computação que estão sendo usados ​​para preencher o espaço criado pela varredura constante.

Os operadores de computação escalar estão sendo carregados com NULL e o valor 1045876, portanto, eles claramente serão usados ​​com a junção de loop, em um esforço para filtrar os dados.

A parte realmente legal é que esse plano é trivial. Isso significa que passou por um processo mínimo de otimização. Todas as operações estão levando ao Intervalo de Mesclagem. Isso é usado para criar um conjunto mínimo de operadores de comparação para uma busca de índice ( detalhes sobre isso aqui ).

Nesta pergunta: Posso obter o SSMS para me mostrar os custos reais da consulta no painel do plano de execução? Estou corrigindo problemas de desempenho em um procedimento armazenado com várias instruções no SQL Server. Quero saber em quais partes devo gastar tempo.

Entendo em Como leio o Custo de consulta e é sempre uma porcentagem? que mesmo quando o SSMS é instruído a incluir o plano de execução real, os números "Custo da consulta (relativo ao lote)" ainda são baseados em estimativas de custo, que podem estar longe dos valores reais

Medindo o desempenho da consulta: "Custo da consulta do plano de execução" vs "Tempo decorrido" fornece boas informações para quando você precisa comparar o desempenho de duas consultas diferentes.

Em Lendo um plano de execução do SQL Server, você pode encontrar ótimas dicas para ler o plano de execução.

Outras perguntas / respostas de que realmente gostei porque são relevantes para esse assunto e, para minha referência pessoal, gostaria de citar são:

Como otimizar a consulta T-SQL usando o Plano de Execução

sql pode gerar um bom plano para esse procedimento?

Os planos de execução diferem para a mesma instrução SQL

Marcello Miorelli
fonte