O sp_executesql pode ser configurado / usado por padrão?

10

Eu estou olhando para um aplicativo que usa consultas sql altamente dinâmicas no SQL Server. Olhando para as consultas que são construídas de maneiras muito estranhas e complicadas, mas essa é uma história diferente, eu digo a ela para dar uma boa razão para eu não ser capaz (muito estúpido) de descobrir as coisas sozinho ... Eu não consigo ver qualquer código em que as consultas sejam agrupadas sp_executesql.

Mas quando rastreio, consigo ver muitas consultas sendo processadas sp_executesql. A solução completa do aplicativo nem sequer contém o comando sp_executesql.

Então, eu me perguntei se existe algum tipo de configuração que ainda não conheço que força o software a agrupar consultas com sp_executesql por padrão?

O que poderia causar esse comportamento?

Magier
fonte

Respostas:

11

O motivo pelo qual as instruções SQL estão sendo agrupadas sp_executesqlé a configuração da SqlCommand.Commandtypepropriedade e a passagem de qualquer Parâmetro para o comando.

SqlCommand cmd = new SqlCommand("proc1", con);
cmd.CommandType = CommandType.StoredProcedure;                
cmd.Parameters.AddWithValue("@param1", 1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();

O código acima termina com este T-SQL:

exec proc1 @param1=1
SqlCommand cmd = new SqlCommand("proc1", con);
cmd.CommandType = CommandType.Text;                
cmd.Parameters.AddWithValue("@param1", 1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();

Este código termina com a execução do seguinte T-SQL:

exec sp_executesql N'proc1',N'@param1 int',@param1=1

Adição 23.12.15: Usando um CommandType.Textcomando, os resultados são semelhantes: Assim que um parâmetro é adicionado ao objeto de comando, o .NET agrupa toda a consulta sp_executesqle passa os parâmetros para ela.

Além disso: após aprofundar sp_executesql, o sniffing de parâmetros e o armazenamento em cache de plano esse comportamento das classes .NET fazem totalmente sentido, a fim de evitar a compilação de consultas freqüentes e o número de planos. Portanto, ele foi basicamente projetado para garantir um melhor desempenho do SQL Server em geral, ao mesmo tempo em que pode levar a um desempenho ruim de algumas consultas (problema de detecção de parâmetro) usadas com valores de parâmetro diferentes do plano de consulta criado inicialmente.

Vejo:

O exemplo acima foi criado usando o .NET Framework 4.5 e o SQL Server 2008 Developer Edition.

Magier
fonte
5

Se este for um aplicativo .NET, é muito provável que o resultado seja chamado SqlCommand.ExecuteReader () . De acordo com a página principal da classe SqlCommand , na grade de descrições de métodos na seção "Comentários", em ExecuteReader, ele diz:

Executa comandos que retornam linhas. Para aumentar o desempenho, o ExecuteReader chama comandos usando o procedimento armazenado do sistema Transact-SQL sp_executesql . Portanto, ExecuteReader pode não ter o efeito desejado, se usado para executar comandos como instruções SET Transact-SQL.

Agora não tenho tempo para testar isso para confirmar sua descrição, mas deve ser fácil criar um aplicativo de console simples que faça uma chamada muito simples, passando algum texto de consulta e incluindo um parâmetro fornecido com a SqlParameter. Meu palpite é esse ExecuteNonQuerye ExecuteScalartambém o uso, sp_executesqlpois eles também permitem a passagem de parâmetros, então por que haveria um caminho diferente para como eles são executados?

Solomon Rutzky
fonte