SQL Server na prática

Por que SQL se comporta diferente na aplicação e no SSMS

Compare opções de sessão, tipos de parâmetros e metadados de módulos para explicar diferenças entre a aplicação e uma janela do SSMS.

Uma consulta funciona no SSMS, mas falha ou fica lenta na aplicação. Copiar o texto não reproduz toda a requisição. A conexão tem configurações, o driver envia metadados de parâmetros e uma procedure pode carregar opções capturadas quando foi criada.

Comparar interpretação antes de otimizar

O exemplo interpreta a mesma data textual com dois DATEFORMAT. Ele guarda e restaura o formato original da sessão.

DECLARE @OriginalFormat nvarchar(3);
SELECT @OriginalFormat = date_format
FROM sys.dm_exec_sessions WHERE session_id = @@SPID;

SET DATEFORMAT dmy;
SELECT TRY_CONVERT(date, '03/04/2023') AS InterpretedAsDMY;

SET DATEFORMAT mdy;
SELECT TRY_CONVERT(date, '03/04/2023') AS InterpretedAsMDY;

SET DATEFORMAT @OriginalFormat;

SELECT
    @@SPID AS SessionId,
    @@LANGUAGE AS SessionLanguage,
    @@DATEFIRST AS FirstDayOfWeek,
    @@LOCK_TIMEOUT AS LockTimeoutMs,
    SESSIONPROPERTY('ANSI_WARNINGS') AS AnsiWarnings,
    SESSIONPROPERTY('ARITHABORT') AS ArithAbort,
    SESSIONPROPERTY('QUOTED_IDENTIFIER') AS QuotedIdentifier;

DBCC USEROPTIONS;

O primeiro resultado é 3 de abril de 2023 e o segundo é 4 de março de 2023. As duas conversões funcionam. Um teste que apenas verifica ausência de erro não encontra a diferença. Uma data válida e incorreta pode ser mais prejudicial que uma falha clara.

Prefira parâmetros de data tipados na aplicação. Se a troca textual for necessária, defina representação inequívoca e estilo de conversão explícito apropriado. Não dependa do idioma do desenvolvedor. DATEFIRST também pode afetar cálculos de dia da semana.

Execute o diagnóstico na conexão real da aplicação quando possível. Uma sessão administrativa separada informa apenas seu próprio estado. Capture também banco, compatibilidade, isolamento e tipos de parâmetros. varchar e nvarchar com o mesmo texto aparente não são metadados iguais.

Separar estado da sessão e do módulo

Algumas opções SET afetam execução, enquanto outras influenciam parsing ou são salvas na criação do módulo. QUOTED_IDENTIFIER define a interpretação de aspas duplas. sys.sql_modules permite conferir uses_quoted_identifier e uses_ansi_nulls de uma procedure.

Mudar uma opção na janela de diagnóstico não regrava automaticamente os metadados capturados. Se uma migração criou o módulo com ajustes indevidos, corrija CREATE ou ALTER deliberadamente e verifique os valores armazenados. Use aspas simples para strings e uma convenção consistente para identificadores.

O comportamento antigo de NULL não é um contorno moderno. SQL Server 2017 e posteriores sempre usam ANSI_NULLS ON. Escreva IS NULL ou IS NOT NULL. Um SET ANSI_NULLS OFF herdado não restaura de forma confiável uma suposição antiga da aplicação.

O pool de conexões também exige clareza. Inicialização e reset pertencem ao provedor. O caminho suportado da aplicação deve estabelecer as opções necessárias, sem depender de uma requisição anterior que preparou a sessão por acaso.

Explicar planos sem uma opção mágica

Algumas opções participam do contexto do cache de planos. Contextos diferentes podem gerar planos diferentes para SQL aparentemente igual. Isso não comprova que alternar ARITHABORT seja a correção de desempenho. Parâmetros compilados, estimativas e caminhos de acesso podem explicar a diferença real.

Capture os dois planos e compare tipos, valores compilados, estimativas e leituras medidas. Reproduza parâmetros representativos da aplicação no mesmo contexto. Um cliente pequeno escolhido no teste interativo não explica uma consulta de produção para um cliente enorme.

Certos recursos de indexação também exigem um conjunto específico de opções. Índices filtrados e sobre colunas calculadas possuem requisitos envolvendo ANSI_WARNINGS, QUOTED_IDENTIFIER e ARITHABORT, além de NUMERIC_ROUNDABORT OFF. Confira o conjunto completo documentado para o recurso.

Observe igualmente configurações transacionais. IMPLICIT_TRANSACTIONS pode deixar trabalho aberto por mais tempo que o esperado. LOCK_TIMEOUT controla espera por locks, não a duração total do comando. Essas diferenças alteram falhas e bloqueios mesmo sem mudança de plano.

Por fim, coloque os ajustes necessários nos caminhos de inicialização e implantação e teste aplicação e execução administrativa. Guarde as opções observadas no registro do incidente. O objetivo é um contrato reproduzível, para que 'funciona na minha janela' seja uma comparação útil em vez de encerrar a análise sem uma causa.

Referências técnicas: Microsoft Learn: SET statements · Microsoft Learn: SET DATEFORMAT · Microsoft Learn: SET QUOTED_IDENTIFIER.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo