Database
 sql >> Base de Dados >  >> RDS >> Database

Acompanhamento das opções do cursor


Observação:esta postagem foi publicada originalmente apenas em nosso eBook, Técnicas de alto desempenho para SQL Server, Volume 3. Você pode descobrir mais sobre nossos eBooks aqui.

Há mais de três anos, escrevi um post sobre opções de cursor no SQL Server e por que você deve substituir os padrões:
  • Qual ​​o impacto que diferentes opções de cursor podem ter?

Eu queria postar um acompanhamento para reiterar que – embora você nunca deva apenas aceitar os padrões – você realmente deve pensar sobre quais opções são mais aplicáveis ​​ao seu cenário. Eu também queria esclarecer alguns itens que surgiram nos comentários desse post.

Andrew Kelly trouxe um grande ponto, e é que um STATIC cursor faz uma cópia única dos resultados, coloca-os em tempdb e evita quaisquer problemas de simultaneidade que possam afetar um DYNAMIC cursor. Uma opção não é uma vencedora clara sobre a outra em todos os casos; por exemplo, você pode ter muitos cursores (ou cursores com conjuntos de resultados muito grandes) e/ou um tempdb já sobrecarregado e não deseja descarregar nenhum estresse adicional lá. Mas é algo digno de teste.

Fabiano também trouxe um grande ponto que tanto DYNAMIC e FAST_FORWARD cursores podem ser vulnerável ao problema do Halloween (discutido por Paul White em uma série de 4 partes, começando aqui). Paul também comentou que FAST_FORWARD pode não ser vulnerável ao problema, dependendo se o otimizador escolheu um plano estático ou dinâmico (Marc Friedman da Microsoft entra em grandes detalhes sobre isso aqui).

Por fim, gostaria de salientar que nem todos os cursores padrão são criados iguais. Executei alguns testes e verifiquei como o SQL Server decidiu definir opções de cursor em vários cenários (validados usando o sys.dm_exec_cursors função de gestão dinâmica). O código é bem simples:
DECLARE c CURSOR FOR [...blah blah...];
SELECT properties FROM sys.dm_exec_cursors(@@SPID);

Aqui estão os resultados para os cenários que testei:
A consulta do cursor é baseada em… Tipo Simultaneidade Escopo
uma constante (FOR SELECT 1 ou FOR SELECT SYSDATETIME() ) Instantâneo Somente leitura Global
uma tabela #temp / ##temp Dinâmico Otimista Global
uma tabela/visualização de usuário Dinâmico Otimista Global
uma visualização de catálogo / DMV Instantâneo Somente leitura Global
uma junção #tmp -> tabela/visualização do usuário Dinâmico Otimista Global
uma junção #tmp -> visualização de catálogo / DMV Instantâneo Somente leitura Global
uma tabela / visualização de usuário de junção -> visualização de catálogo / DMV Instantâneo Somente leitura Global

Crédito onde o crédito é devido – esta investigação foi desencadeada por uma resposta de Jeroen Mostert no Stack Overflow.

Portanto, você deve estar ciente de que as opções padrão do seu cursor, se você não as substituir, podem ser diferentes dependendo da consulta subjacente ao cursor. Se você espera um comportamento específico em um ou em todos os casos, adquira o hábito de especificar explicitamente as opções desejadas.

Mas, na verdade, a questão é…


…pare de usar cursores. Existem realmente muito poucos problemas hoje em que a melhor solução é um cursor, especialmente se você estiver no SQL Server 2012 ou melhor – onde praticamente todos os problemas tradicionalmente resolvidos por cursores podem ser resolvidos usando aprimoramentos nas funções de janela. Se você ainda sentir que precisa usar cursores, siga os conselhos deste post e seu antecessor para determinar quais opções você deve usar.