Degradação repentina do desempenho do SQL Server

13

Eu tenho um SQL Server 2005 que se tornou imprevisível ultimamente e estou coçando a cabeça por que. As consultas executadas em segundos estão alterando os planos e demorando minutos (gastando o tempo na varredura completa da tabela ou no spool de índice). Agora, a primeira e mais óbvia é que as estatísticas estão obsoletas, causando confusão no otimizador, mas estou convencido de que esse não é o caso - primeiro porque os dados subjacentes não estão mudando significativamente (por exemplo, adicionando dados de um dia sobre os dados de um ano já em uma tabela) e, em segundo lugar, porque as Estatísticas de criação automática e Estatísticas de atualização automática são verdadeiras. No entanto, o otimizador está ficando confuso; executar o SQL no Tuning Advisor fornece várias CREATE STATISTICSinstruções de várias colunas que parecem corrigi-lo (até o próximo bit do SQL se comportar mal).

Alguma idéia de uma estratégia que eu possa usar para abordar isso que causa raiz? Por que as estatísticas "normais" não são suficientes?

Gaius
fonte

Respostas:

8

Se sua principal espera for SOS_SCHEDULER_YIELD, parece que você tem alguma pressão na CPU. Mas isso pode ser o resultado de outra coisa, como seu design não ser mais suficiente para suas consultas. Sei que você disse que está apenas adicionando dados de um dia, mas pode ter atingido um ponto de inflexão.

Como suas consultas estão sendo emitidas? É SQL dinâmico? Você está usando procedimentos armazenados? Você está usando sp_executesql? É possível que você tenha um caso de sniffing de parâmetros? Como é o design do seu db? Quais são os relacionamentos PK e FK?

Você tem um exemplo de um bom plano? Se você conseguir determinar um bom plano, poderá usar guias de plano para forçar a execução da consulta de uma maneira específica.

Você pode dar um exemplo de um bom plano que deu errado?

Por fim, pegue uma cópia do sp_whoIsActive ( http://whoisactive.com/ ) de Adam Machanic e use-a para determinar mais sobre as consultas em execução. E se você deseja capturar a saída de sp_whoIsActive, acesse aqui http://www.littlekendra.com/2011/02/01/whoisactive/

SQLRockstar
fonte
É um aplicativo de terceiros, não tenho controle sobre seu esquema ou SQL, o que é bastante horrível, muitas consultas parametrizadas (por exemplo where col=(cast @var...)) e @varpodem ser '%'. Eu o herdei há uma ou duas semanas e preciso mantê-lo funcionando basicamente até que seja substituído. Obrigado pelo link, eu vou dar uma olhada.
Gaius
A próxima maior espera depois SOS_SCHEDULER_YIELDfoi CXPACKETe sp_configure "max degree of parallelism", 1parece ter - por enquanto - derrubado os dois problemas na cabeça. Obrigado!
Gaius
+1 para o link para sp_whoIsActive
Jeff
8

Do MSDN :

" Operações de inserção ocorrem em colunas-chave ascendentes ou descendentes As estatísticas em colunas-chave ascendentes ou descendentes, como IDENTITY ou colunas de carimbo de data / hora em tempo real, podem exigir atualizações de estatísticas mais frequentes do que o otimizador de consultas executa. As operações de inserção acrescentam novos valores às colunas ascendentes ou descendentes O número de linhas adicionadas pode ser muito pequeno para acionar uma atualização de estatísticas.Se as estatísticas não estiverem atualizadas e as consultas forem selecionadas das linhas adicionadas mais recentemente, as estatísticas atuais não terão estimativas de cardinalidade para esses novos valores. resultam em estimativas imprecisas de cardinalidade e desempenho lento da consulta.

Por exemplo, uma consulta que seleciona as datas mais recentes do pedido de vendas terá estimativas imprecisas de cardinalidade se as estatísticas não forem atualizadas para incluir estimativas de cardinalidade para as datas mais recentes do pedido de vendas.

Operações após a manutenção Considere atualizar as estatísticas após executar procedimentos de manutenção que alteram a distribuição dos dados, como truncar uma tabela ou executar uma inserção em massa de uma grande porcentagem das linhas. Isso pode evitar atrasos futuros no processamento de consultas enquanto as consultas aguardam atualizações automáticas de estatísticas ".

Você pode usar "EXEC sp_updatestats" de tempos em tempos em seu sistema (agendado algum tempo) ou usar a função STATS_DATE em todos os objetos e ver quando suas estatísticas foram atualizadas na última vez e se houve muito tempo desde então, use UPDATE ESTATÍSTICAS para esse objeto em particular. Na minha experiência, mesmo com as estatísticas automáticas ativadas, ainda somos obrigados a atualizar as estatísticas periodicamente, devido a operações de inserção que não acionam a atualização automática.

Para adicionar meu código pessoal (usado em um trabalho semanal que cria instruções dinâmicas para atualização de estatísticas):

select distinct
        'update statistics [' + stats.SchemaName + '].[' + stats.TableName + ']'
            + case when stats.RowCnt > 50000 then ' with sample 30 percent;'
            else 
                ';' end
        as UpdateStatement
    from (
        select
            ss.name SchemaName,
            so.name TableName,
            so.id ObjectId,
            st.name AS StatsName, 
            STATS_DATE(st.object_id, st.stats_id) AS LastStatisticsUpdateDate
            , si.RowModCtr
            , (select case si2.RowCnt when 0 then 1 else si2.RowCnt end from sysindexes si2 where si2.id = si.id and si2.indid in (0,1)) RowCnt
        from sys.stats st
            join sysindexes si on st.object_id = si.id and st.stats_id = si.indid
            join sysobjects so on so.id = si.id and so.xtype = 'U' --user table
            join sys.schemas ss on ss.schema_id = so.uid
    ) stats
    where cast(stats.RowModCtr as float)/cast(stats.RowCnt as FLOAT)*100 >= 10 --more than 10% of the rows have changed
    or ( --update statistics that were not updated for more than 3 months (and rows no > 0)
        datediff(month, stats.LastStatisticsUpdateDate, getdate()) >= 3
        and stats.RowCnt > 0
    )

Aqui eu recebo todos os objetos em que as estatísticas não foram atualizadas por mais de três meses ou, desde a última atualização, houve mais de 10% das linhas alteradas.

Marian
fonte
Hmm, meu principal evento de espera é, SOS_SCHEDULER_YIELDmas não posso dizer agora se isso se deve aos planos ruins ou se essa caixa (6 anos, 2 processadores, 4G RAM) está realmente sobrecarregada agora e eu já foi sobre algum ponto de inflexão.
Caio
em vez de apenas executar essa consulta para criar as instruções UPDATE e executá-las manualmente, você pode usar um cursor com base nessa instrução select para fazer um loop nos resultados executando-os usando chamadas para sp_executesql - dessa forma, você pode executá-la automaticamente (por exemplo, como parte de um plano de manutenção durante a noite (ou outro período silencioso)).
David Spillett
@ David: é isso que estou fazendo no trabalho semanal :). Acabei de formatá-lo de maneira diferente para o Gaius ver a saída que estou usando. O script inicial era muito feio e longo. Obrigado pela ajuda com a formatação! Você pode me enviar para um tutorial de formatação .. porque eu realmente não sei como tornar o código bonito aqui. Obrigado!
Marian
existe um link "ajuda de formatação" na tela "editar resposta" e, como um ícone à direita acima da caixa de resposta inicial na página principal da pergunta, que lista a sintaxe de redução suportada por esses sites.
David Spillett 12/03
3
As estatísticas de atualização automática são acionadas em 20% + 500 linhas, não em 10%.
mrdenny
3

Meu palpite é que uma ou mais de suas tabelas estão ficando grandes o suficiente para não atingir as 20% das alterações necessárias para ajudar a marcar essas estatísticas atuais como obsoletas, para que as Estatísticas de Atualização Automática entrem em ação e ainda assim haja atualizações suficientes (ou inserções) ) que ter estatísticas atualizadas ajudaria muito. Encontrei a mesma coisa recentemente em um ambiente específico após a atualização do SQL 2000 para o SQL 2008.

Além dos outros sites mencionados nas respostas acima, sugiro verificar os seguintes recursos online.

1) O Red-Gate tem vários e-books gratuitos disponíveis para download, incluindo "Estatísticas do SQL Server" de Holger Schmeling, onde você encontrará a seguinte citação:

http://www.red-gate.com/our-company/about/book-store/

"tabelas com mais de 500 linhas, pelo menos 20% dos dados de uma coluna tiveram que ser alteradas para invalidar as estatísticas vinculadas"

2) O SQL Sentry possui uma ferramenta gratuita do Plan Explorer que ajuda a rastrear problemas em um plano SQL, como uma estimativa de muitas ou poucas linhas em comparação com o número real de linhas para uma determinada tabela em uma consulta. Apenas salve o plano de execução real do SSMS e percorra as diferentes partes do plano usando o Plan Explorer. Não é que as informações não estejam disponíveis no SSMS usando o plano de execução gráfica, mas a ferramenta do SQL Sentry facilita muito a visualização.

http://www.sqlsentry.com/plan-explorer/sql-server-query-view.asp

3) Verifique você mesmo a data de atualização das estatísticas nas tabelas nas consultas que você mais deseja usar STATS_DATE (); você pode encontrar uma consulta rápida para obter as estatísticas mais antigas usando uma consulta encontrada na discussão a seguir.

http://blog.sqlauthority.com/2010/01/25/sql-server-find-statistics-update-date-update-statistics/

Eu espero que isso ajude!

Eu acho que você vai gostar especialmente do livro da Red-Gate!

-Jeff

Jeff
fonte
Obrigado, vou trabalhar o meu caminho através deles. Eu sou principalmente um DBA Oracle que herdou esse sistema (embora eu não seja preconceituoso com o SQL Server, pelo que vejo desde 2005 é uma plataforma muito capaz, eu simplesmente não a conheço tão bem quanto a Oracle) .
Gaius