O Prompt SQL é uma ferramenta prática de prompt de sintaxe SQL. O SQL Prompt pesquisa automaticamente de acordo com o nome do objeto, gramática e fragmentos de código do banco de dados e fornece aos usuários a seleção de código apropriada. As configurações automáticas de script tornam o código simples e fácil de ler - especialmente útil quando os desenvolvedores não estão familiarizados com scripts. O SQL Prompt está instalado e pronto para uso, o que pode melhorar muito a eficiência da codificação. Além disso, os usuários podem personalizá-lo conforme necessário para que funcione da maneira esperada.
O Prompt SQL implementa duas regras de análise de código estático para verificar se o código pode abusar do comando SET NOCOUNT:
- PE008 - DEFINIR NOCOUNT OFF uso
- PE009-SET NOCOUNT ONDML não antes
Sempre que uma consulta é executada, uma mensagem curta será retornada ao cliente, que contém o número de linhas afetadas pela instrução T-SQL. Ao usar SET NOCOUNT ON, esta mensagem não será enviada. Isso pode melhorar o desempenho reduzindo ligeiramente o tráfego da rede. É melhor usar SET NOCOUNT ON em gatilhos e procedimentos armazenados do SQL Server, a menos que um ou mais aplicativos que usam procedimentos armazenados exijam que ele seja definido como OFF porque estão lendo o valor na mensagem. SET NOCOUNT ON não afetará os resultados retornados. DONE_IN_PROC para cada instrução executada, ele apenas suprime os pacotes de mensagem redundantes, caso contrário, ele enviará esses pacotes de mensagem de volta ao cliente como os chamados pacotes de mensagem pequenos (nove bytes). A lógica baseada no servidor e os valores como @@ ROWCOUNT não são afetados.
Por padrão, SET NOCOUNT é definido como OFF no nível da instância do SQL Server, o que significa que DONE_IN_PROC enviará uma mensagem ao cliente para cada instrução no procedimento armazenado. Ao usar os utilitários fornecidos para executar consultas com o Microsoft SQL Server, a mensagem "Linha NN é afetada" será padronizada para o final das instruções Transact-SQL como SELECT, INSERT, UPDATE e DELETE.
A Microsoft recomenda o uso seletivo de SET NOCOUNT ON no nível da sessão para evitar que essas mensagens sejam enviadas: "Para procedimentos armazenados que contêm várias instruções que não retornam grandes quantidades de dados reais, eliminar essas mensagens pode melhorar significativamente o desempenho devido à grande quantidade de o tráfego da rede. diminui muito ".
Em geral, a melhor abordagem é evitar o envio de mensagens de contagem de linha (a menos que precisem ser enviadas), mas a parte complicada é acomodar aplicativos mais antigos que usam e frequentemente abusam dessas mensagens. Além disso, para o processamento assíncrono do processo pela camada intermediária de um aplicativo de banco de dados (como ORM), o envio dessas mensagens pode às vezes se tornar um problema. Em comparação com o resultado do procedimento armazenado, a mensagem de contagem de linhas é transmitida ao cliente muito mais lentamente, o que pode bloquear o thread.
O que é uma mensagem?
A conexão com o banco de dados transmite dados e mensagens separadamente. No Management Studio (SSMS), quando os resultados da consulta são apresentados como uma grade, eles são representados por painéis separados na janela de consulta. Quando a conexão sqlClient é feita, o manipulador InfoMessage pode ler o fluxo de mensagens. Para permitir que o cliente leia e processe avisos ou mensagens enviadas pelo servidor, o cliente pode ouvir essas mensagens por meio do delegado SqlInfoMessageEventHandler que pode responder a esses eventos.
Neste artigo, enfocamos apenas um tipo de mensagem. Rows. No entanto, o SQL Server também pode enviar mensagens em resposta a comandos específicos. Até mesmo RAISERROR (gravidade 10 ou inferior) e o trio de instruções PRINT e instruções SET STATISTICS (SET STATISTICS IO ON, SET STATISTICS TIME ON, SET STATISTICS XML ON). Meu artigo "Teste regular de SQL DML para testadores não entusiasmados" ilustra o valor de usar esse fluxo de mensagens ao monitorar o desempenho. O comando SET NOCOUNT determina apenas se deve enviar uma mensagem de contagem de linha.
Vários aplicativos, componentes, widgets (como grades) e middleware (como ORM) usam mensagens de contagem de linhas para obter a contagem atual dos resultados de dados. Mesmo na mesma situação, muitas vezes é difícil combinar a consulta com a mensagem de contagem. Sessão Muitas outras consultas são executadas, o que também pode causar bloqueio de thread. É melhor fechar essas mensagens SET NOCOUNT ON de contagem de linhas no código de retorno do procedimento ou por meio do uso de variáveis de saída e usar o valor return count @@ ROWCOUNT. No entanto, muitos códigos antigos precisam ser acomodados.
Qual é o escopo de SET NOCOUNT?
Depois de estabelecer uma conexão com o SQL Server e iniciar uma sessão, você só precisa definir NOCOUNT uma vez, o que afetará tudo o que você fizer naquela sessão. SET A instrução que você fizer mudará apenas o processamento de informações específicas na sessão atual; cada lote que você executar naquela sessão herdará essas configurações.
Se SET executar uma instrução em um procedimento armazenado ou gatilho, SET restaurará o valor anterior da opção após retornar o controle do procedimento armazenado ou gatilho. Da mesma forma, se SET NOCOUNT tiver uma instrução EXECUTE na string SQL dinâmica que é executada usando sp_executesql ou, o valor inicial da opção será restaurado depois que SET executar a string SQL dinâmica. Portanto, não há necessidade de definir explicitamente NOCOUNT no final do procedimento armazenado ou gatilho.
Exceto para procedimentos, gatilhos e lotes executados dinamicamente, todas as configurações na sessão NOCOUNT permanecerão na sessão até serem alteradas.
Quais são as vantagens de desempenho de SET NOCOUNT ON?
Usando um procedimento armazenado bem projetado, você obterá apenas uma melhoria de desempenho insignificante NOCOUNT substituindo as configurações padrão de todo o servidor. Em outras palavras, em circunstâncias especiais, o uso de SET NOCOUNT ON trará grandes benefícios. Tudo depende do número e da frequência das consultas executadas no processo. Por exemplo, se um processo está usando cursores para executar muitas consultas, os resultados dessas consultas fazem parte da consulta retornada ou o processo contém muitas instruções que não retornam uma grande quantidade de dados reais, o processo pode ser executado e comparado para a velocidade Dez vezes NOCOUNT OFF, porque o tráfego de rede é muito reduzido. Apenas uma ou duas consultas são executadas no processo, e a receita será inferior a 5%.
Por que não apenas habilitar NOCOUNT no nível da instância do banco de dados?
As definições de configuração do servidor de opções do usuário especificam "padrão global" para cada opção SET, incluindo NOCOUNT. Por padrão, a instância do SQL Server será desabilitada por NOCOUNT, portanto, cada instrução emitida no banco de dados nessa instância resultará no retorno de uma mensagem no final, indicando o número de linhas afetadas.
Você pode usar sp_configure para modificar o comportamento em nível de instância para habilitar NOCOUNT e evitar que essas mensagens sejam enviadas, conforme mostrado na Listagem 1. Isso afetará as configurações padrão para todas as sessões de usuário iniciadas após as configurações serem feitas.
EXEC sys.sp_configure'user options ',' 512 '; - 512 = NOCOUNT
Listagem 1
Os usuários podem substituir os valores padrão no nível do servidor emitindo instruções SET NOCOUNT que afetam apenas sua única sessão.
Os gatilhos não devem enviar mensagens de contagem de linhas; não há exceções a esta regra. Na verdade, se a camada de aplicativo intermediária espera certas mensagens de contagem de linha e usa SET NOCOUNT OFF para acionadores, isso pode causar erros aleatórios estranhos. Até mesmo a grade de dados do SSMS pode estar ofendendo o problema do gatilho.
No entanto, em outros lugares, existem muitas exceções. Se você tiver algum componente antigo que use as mensagens de contagem de linhas retornadas para acessar o banco de dados, bloquear essas mensagens no nível da instância pode causar problemas. Normalmente, esses componentes podem ser facilmente acomodados pela configuração adequada dos procedimentos armazenados sendo usados por esses componentes por meio de NOCOUNT. No entanto, se eles acessarem a tabela diretamente e você não puder adicionar SET NOCOUNT OFF para essas sessões, não seria aconselhável alterar as configurações de nível de instância do banco de dados.
Da mesma forma, se um componente do aplicativo (como ORM ou LINQ) está abusando dessa mensagem para determinar o número de linhas do resultado, se você desligar a mensagem, algo ruim pode acontecer.
Que dano acontecerá se você ativar o NOCOUNT?
Se você usar DataAdaptor para chamar procedimentos armazenados do SQL Server para editar ou excluir dados, não use SET NOCOUNT ON na definição de procedimento armazenado. Isso fará com que a contagem de linhas afetadas volte a zero e o DataAdapter emita uma DBConcurrencyException. Na verdade, uma programação defensiva sábia significa que SET NOCOUNT OFF emite recomendações claras nessas situações.
A classe sqlclient.sqlcommand também pode encontrar problemas com SET NOCOUNT ON, que podem ser causados pela maneira como o cliente usa ODBC. Quando o aplicativo chama SQLRowCount, a mensagem de contagem de linhas está disponível no ODBC. Esta não é uma informação confiável porque algumas fontes de dados não podem retornar o número de linhas no conjunto de resultados antes que o resultado seja obtido.
Mesmo no SQL Server, esse valor só é confiável se você NOCOUNT testar subsequentemente o "estado" após ler SQLRowCount. Quando a opção NOCOUNT é definida como on, SQLROWCOUNT retorna 0, mesmo se houver resultados. Se SQLRowCount retornar 0, o aplicativo deve determinar se NOCOUNT é testando o valor da propriedade específica do SQL Server. Se esse valor for retornado, o valor de SQLRowCount de 0 significa apenas que o SQL Server não retornou o número de linhas. Se retornar, significa que está fechado e o valor em SQLRowCount é 0ONSQL_SOPT_SS_NOCOUNT_STATUSSQL_NC_ONSQL_NC_OFFNOCOUNT indicando que a instrução não afeta nenhuma linha, portanto, não há necessidade de processar o resultado.
Então, quais são as recomendações de "melhores práticas"?
Uma sugestão simples viável é manter o estado padrão do nível da instância do banco de dados inalterado e SET NOCOUNT ON para adicionar um no início de cada procedimento armazenado, gatilho e lote executado dinamicamente. Esta regra se aplica a todos os gatilhos, sem exceção. Os procedimentos armazenados também não precisarão dessas mensagens, a menos que o aplicativo que está tentando usá-los para obter a contagem de linhas do resultado os chame de fora do banco de dados. Geralmente, é melhor usar o valor em @@ RowCount para enviar a contagem para a variável de saída, mas isso não ajuda os componentes de aplicativo pré-existentes. Se você precisar garantir que a consulta retorne uma mensagem de contagem de linha, você deve especificá-la em vez de usar a configuração atual.