Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

O desempenho da consulta do Entity Framework difere extremamente com a execução de SQL bruto


Nesta resposta, estou focando na observação original:a consulta gerada pelo EF é lenta, mas quando a mesma consulta é executada no SSMS é rápida.

Uma possível explicação para esse comportamento é Sniffing de parâmetros .

Portanto, o EF gera uma consulta que possui poucos parâmetros. Na primeira vez que você executa essa consulta, o servidor cria um plano de execução para essa consulta usando valores de parâmetros que estavam em vigor na primeira execução. Esse plano geralmente é muito bom. Mas, mais tarde, você executa a mesma consulta EF usando outros valores para parâmetros. É possível que para novos valores de parâmetros o plano gerado anteriormente não seja o ideal e a consulta fique lenta. O servidor continua usando o plano anterior, pois ainda é a mesma consulta, apenas os valores dos parâmetros são diferentes.

Se neste momento você pegar o texto da consulta e tentar executá-lo diretamente no SSMS, o servidor criará um novo plano de execução, pois tecnicamente não é a mesma consulta que é emitida pelo aplicativo EF. Mesmo uma diferença de caractere é suficiente, qualquer alteração nas configurações da sessão também é suficiente para que o servidor trate a consulta como uma nova. Como resultado, o servidor tem dois planos para a mesma consulta em seu cache. O primeiro plano "lento" é lento para os novos valores de parâmetros, porque foi originalmente construído para diferentes valores de parâmetros. O segundo plano "rápido" é construído para os valores de parâmetro atuais, portanto, é rápido.

O artigo Lento no aplicativo, rápido no SSMS por Erland Sommarskog explica esta e outras áreas relacionadas com muito mais detalhes.

Existem várias maneiras de descartar planos em cache e forçar o servidor a regenerá-los. Alterar a tabela ou alterar os índices da tabela deve fazê-lo - deve descartar todos os planos relacionados a esta tabela, tanto "lentos" quanto "rápidos". Em seguida, você executa a consulta no aplicativo EF com novos valores de parâmetros e obtém um novo plano "rápido". Você executa a consulta no SSMS e obtém um segundo plano "rápido" com novos valores de parâmetros. O servidor ainda gera dois planos, mas ambos os planos são rápidos agora.

Outra variante é adicionar OPTION(RECOMPILE) à consulta. Com esta opção o servidor não armazenaria o plano gerado em seu cache. Portanto, toda vez que a consulta é executada, o servidor usaria valores de parâmetro reais para gerar o plano que (ele acha) seria ideal para os valores de parâmetro fornecidos. A desvantagem é uma sobrecarga adicional da geração do plano.

Lembre-se, o servidor ainda pode escolher um plano "ruim" com essa opção devido a estatísticas desatualizadas, por exemplo. Mas, pelo menos, o sniffing de parâmetros não seria um problema.

Aqueles que querem saber como adicionar OPTION (RECOMPILE) dica para a consulta que é gerada pelo EF dê uma olhada nesta resposta:

https://stackoverflow.com/a/26762756/4116017