Por que SET ARITHABORT ON aceleraria drasticamente uma consulta?

75

A consulta é uma única seleção que contém muitos níveis de agrupamento e agrega operações. Com SET ARITHABORT ON, leva menos de um segundo, caso contrário, leva vários minutos. Vimos esse comportamento no SQL Server 2000 e 2008.

Jonathan Allen
fonte

Respostas:

62

Um pouco datado, mas para quem acaba aqui com um problema semelhante ...

Eu tive o mesmo problema. Para mim, acabou sendo um farejamento de parâmetros, que no começo eu não entendia o suficiente para me preocupar. Adicionei um 'set arithabort on' que resolveu o problema, mas depois ele voltou. Então eu li:

http://www.sommarskog.se/query-plan-mysteries.html

Tudo esclareceu tudo. Como estava usando o Linq to SQL e tinha opções limitadas para corrigir o problema, acabei usando um guia de plano de consulta (consulte o final do link) para forçar o plano de consulta desejado.


fonte
3
Mais de seis anos depois, o link fornecido nesta resposta ainda é "leitura obrigatória" ... e ainda atual, sendo a última revisão em dezembro de 17.
takrl
30

Aplicativos .NET se conectam com a opção desabilitada por padrão, mas é habilitada por padrão no Management Studio. O resultado é que o servidor realmente armazena em cache 2 planos de execução separados para a maioria / todos os procedimentos. Isso afeta a maneira como o servidor executa cálculos numéricos e, como tal, você pode obter resultados muito diferentes, dependendo do procedimento. Essa é realmente apenas uma das 2 maneiras comuns pelas quais um processo pode receber um plano de execução terrível, sendo a outra a detecção de parâmetros.

Dê uma olhada em https://web.archive.org/web/20150315031719/http://sqladvice.com/blogs/gstark/archive/2008/02/12/Arithabort-Option-Eption-Effects-Stored-Procedure-Performance. aspx para um pouco mais de discussão sobre isso.

Ben Hoffman
fonte
Eu concordo com metade desta resposta. Estou muito cético sobre a reivindicação de cálculo numérico!
Martin Smith
2
@ Martin: Eu acho que não estava claro. Eu estava apenas dizendo que o ARITHABORT ON faz com que o SQL Server tenha erro em qualquer erro de estouro div / 0 ou aritmético. Quando desligado, ele continua e, por qualquer motivo, pode causar todos os tipos de problemas horríveis.
@ Ben - Sim, desculpe, eu não queria atacar particularmente a sua resposta, eu estava apenas apontando que seria muito fácil alterar uma SETopção, obter um plano melhor e diagnosticar isso como sendo a própria opção que está com falha. Não estou convencido de que o cara no seu link não tenha feito isso.
Martin Smith
@ Martin - Não é um problema, eu não acho que você estava me atacando. A outra discussão que liguei pode ser um pouco incerta. Eu só estava tentando dar evidências de apoio.
@ Martin Em retrospecto, acredito que você está correto.
21

Eu argumentaria que isso era quase certamente um farejamento de parâmetros.

Afirma-se frequentemente que isso SET OPTIONSpode afetar o desempenho dessa maneira, mas ainda tenho que ver uma única fonte autorizada para essa reivindicação, exceto no caso em que você está usando Visualizações indexadas / colunas computadas persistentes.

Nesse caso (para SQL2005 + e a menos que seu banco de dados esteja no modo de compatibilidade com SQL2000 ). Se você tiver os dois ARITHABORTe, em ANSI_WARNINGS OFFseguida, descobrirá que o índice não está sendo usado, pode haver uma varredura em vez da busca desejada (e algumas despesas gerais, pois o resultado do cálculo persistente não pode ser usado). O ADO.NET parece ter como padrão ANSI_WARNINGS ONum teste rápido que acabei de fazer.

A alegação na resposta de Ben de que "a maneira como o servidor executa cálculos numéricos" pode adicionar minutos a um resultado que, de outra forma, levaria menos de um segundo, não me parece credível. Acho que o que costuma acontecer é que, ao investigar um problema de desempenho, o Profiler é usado para identificar a consulta incorreta. Isso é colado no estúdio de gerenciamento e é executado e retorna resultados instantaneamente. A única diferença aparente entre as conexões é a ARITH_ABORTopção.

Um teste rápido em uma janela do estúdio de gerenciamento mostra que quando SET ARITHABORT OFFé ativada e a consulta é executada, o problema de desempenho se repete e, aparentemente, o caso está encerrado. Na verdade, essa parece ser a metodologia de solução de problemas usada no link Gregg Stark .

No entanto, isso ignora o fato de que, com essa opção definida, você pode obter o mesmo plano incorreto do cache .

Essa reutilização do plano pode ocorrer mesmo se você estiver conectado como um usuário diferente do que a conexão do aplicativo usa.

Eu testei isso executando uma consulta de teste primeiro em um aplicativo Web e depois no estúdio de gerenciamento com SET ARITHABORT OFFe pude ver as contas de usuário subindo na consulta abaixo.

SELECT usecounts, cacheobjtype, objtype, text ,query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 

Para que esse compartilhamento pf ocorra, todas as chaves de cache do plano devem ser iguais. Além de arithabortoutros exemplos, os usuários em execução precisam do mesmo esquema padrão (se a consulta depender da resolução implícita de nomes) e as conexões precisam do mesmo languageconjunto.

Uma lista completa de chaves de cache do plano aqui

Martin Smith
fonte
13

Sei que estou atrasado para esta festa, mas para futuros visitantes, Martin está exatamente correto. Corremos para o mesmo problema - um SP estava sendo executado muito lentamente para clientes .NET, enquanto era rápido para o SSMS. Ao explorar e resolver o problema, fizemos os testes sistemáticos sobre os quais Kenny Evitt pergunta em seu comentário à pergunta de Martin.

Usando uma variante da consulta de Martin, procurei o SP no cache do procedimento e encontrei dois deles. Olhando para os planos, era de fato um com o ARITHABORT ON e outro com o ARITHABORT OFF. A versão ARITHABORT OFF teve uma busca de índice, enquanto a versão ARITHABORT ON usou uma varredura de índice para a mesma saída. Dados os parâmetros envolvidos, a busca do índice exigiria uma pesquisa em dezenas de milhões de registros para a saída.

Limpei os dois procedimentos do cache e o cliente .NET executou o SP novamente, usando os mesmos parâmetros (que apresentavam um amplo intervalo de datas para um cliente com muita atividade). O SP voltou instantaneamente. O plano em cache usava a mesma varredura de índice anteriormente apresentada no plano ARITHABORT ON - mas desta vez o plano era para ARITHABORT OFF. Executamos o SP com os mesmos parâmetros no SSMS e, novamente, obtivemos resultados instantaneamente. Agora vimos que um segundo plano foi armazenado em cache, para ARITHABORT ON, com a varredura de índice.

Em seguida, limpamos o cache, executamos o SP no SSMS com um intervalo de datas restrito e obtivemos um resultado instantâneo. Descobrimos que o plano em cache resultante tinha uma busca de índice, pois a mesma saída foi tratada anteriormente com uma varredura (que também era uma busca no plano original com ARITHABORT OFF). Novamente no SSMS, executamos o SP, desta vez com o mesmo amplo intervalo de datas e vimos o mesmo desempenho terrível que tivemos na solicitação .NET original.

Em suma, a disparidade não tinha nada a ver com o valor real do ARITHABORT - com ele ligado ou desligado, de qualquer cliente, poderíamos obter um desempenho aceitável ou terrível: o que importava eram os valores dos parâmetros usados ​​na compilação e no cache do plano.

Embora o MSDN indique que o próprio ARITHABORT OFF pode ter um impacto negativo na otimização de consultas, nossos testes confirmam que Martin está correto - a causa foi a detecção de parâmetros e o plano resultante não é o ideal para todos os intervalos de parâmetros.

mdoyle
fonte
1
Pergunto o que essa frase Setting ARITHABORT to OFF can negatively impact query optimization leading to performance issues.significa. Se eles estão apenas falando sobre incapacidade de usar índices em colunas e visualizações computadas (se ANSI_WARNINGStambém estiver desativada) ou se realmente têm algum outro efeito.
Martin Smith
Não tenho certeza. Eu me pergunto se é simplesmente o caso de alguém no MSDN ter uma situação semelhante, definir ARTIHABORT como ON, ver a melhoria de desempenho e tirar as mesmas conclusões que outras pessoas têm. Quanto às visualizações indexadas e às colunas computadas, não estou claro. Em um ponto, ele afirma que as opções SET devem ter valores específicos se uma operação INSERT, UPDATE ou DELETE modificar os valores de dados armazenados nela. Em outros lugares, eles afirmam que o otimizador ignorará os índices de "qualquer consulta" que faça referência à referida exibição indexada ou coluna computada. Ambos são verdadeiros ou são realmente "dados de modificação de consulta"?
Mdyle # 1
1

Só tive esse problema. Como as pessoas disseram aqui, a causa raiz é vários planos de consulta, um dos quais é subótimo. Eu só queria verificar se o ARITHABORT pode realmente causar o problema por si só (como a consulta com a qual eu estava tendo problemas não tinha parâmetros, o que tira o farejamento de parâmetros da equação).

Alan D. Nelson
fonte
1

Isso me lembra exatamente o mesmo problema que experimentei nos dias sql server 2008. No nosso caso, descobrimos repentinamente um trabalho sql abrandando repentinamente (geralmente alguns segundos e agora mais de 9 minutos), o trabalho precisa acessar um servidor vinculado, adicionamos o conjunto ARITHABORT na etapa do trabalho e parecia o problema foi resolvido por alguns dias e depois retornou.

Posteriormente, abrimos um ticket com suporte da MS e, inicialmente, eles também não puderam descobrir, e o ticket foi escalado para uma equipe de PFE muito sênior, e dois PFEs de suporte tentaram descobrir esse problema.

O motivo final é que a credencial do usuário (para executar a etapa da tarefa) não pode acessar as estatísticas das tabelas subjacentes (no lado do servidor vinculado) e, portanto, o plano de execução não é otimizado.

Em detalhes, o usuário não tem permissão no DBCC SHOW_STATISTICS (embora o usuário possa SELECT da tabela). De acordo com o MSDN , essa regra de permissão é alterada após o sql 2012 SP1

Permissões para o SQL Server e o banco de dados SQL

Para visualizar o objeto de estatísticas, o usuário deve possuir a tabela ou ser membro da função de servidor fixa sysadmin, da função de banco de dados fixa db_owner ou da função de banco de dados fixa db_ddladmin.

O SQL Server 2012 SP1 modifica as restrições de permissão e permite que os usuários com permissão SELECT usem esse comando. Observe que existem os seguintes requisitos para que as permissões SELECT sejam suficientes para executar o comando:

Para verificar esse problema, precisamos apenas executar o criador de perfil na instância vinculada do servidor e ativar alguns eventos na seção "Erros e avisos", como mostrado abaixo.

insira a descrição da imagem aqui

Espero que essa experiência possa ajudar a comunidade de alguma forma.

jyao
fonte