Atualização de estatisticas manual em ambientes de alta disponibilidade

Todos sabemos que uma consulta de banco de dados pode se basear em regrar Heuristicas ou em Estatisticas para chegar no melhor plano de execução, ou seja, aquele que consome menos tempo e menos processamento.
No SQL Server, é possivel a criação de estatisticas automatica ou manual, assim como sua atualização automatica, automatica não sincrona e manual.

Para ambientes de alta disponibilidade, é complicado realizar atualizações em tempo real, ou até em tempo real não sincrona, portanto, desenvolvi a query abaixo, que faz o seguinte:
1. Seleciona todas as tabelas e a ultima data de sua atualização.
2. Atualiza as estatisticas da tabela da mais antiga para a mais nova em relação a ultima atualização.
3. Dado determinado horario, ela para de executar.

No dia seguinte de sua execução portanto, sera atualizada as tabelas que não foram atualizadas anteriormente, mantendo assim um fila reciclavem, sem onerar seu ambiente, normalmente a mesma é executada de madrugada, na maioria dos casos é claro….

A procedure abaixo em si esta com o termino previsto para as 07:00, e o inicio da mesma se tem ao inicio do job em que ela foi agendada, para visualisar como agendar um job, clique aqui.

CREATE PROCEDURE [dbo].[UpDateStatsTime]  
AS  
--CRIA TABELA TEMPORARIA  
CREATE TABLE ##Principal(Base VARCHAR(100), Tabela VARCHAR(500), [Update] DATETIME)  
  
--FAZ CARGA DE TABELAS E BASES  
exec sp_msforeachdb 'if ''@'' not in (''tempdb'')  
BEGIN  
use @;  
INSERT INTO ##Principal  
SELECT ''@'', Table_Name,MIN(Date_updated) as Date  
FROM (  
SELECT           
  t.name AS Table_Name  
        ,i.name AS Index_Name  
        ,i.type_desc AS Index_Type  
        ,STATS_DATE(i.object_id,i.index_id) AS Date_Updated  
FROM         
  sys.indexes i JOIN  
  sys.tables t ON t.object_id = i.object_id  
WHERE           
  i.type > 0   
--ORDER BY  
  --t.name ASC  
 --,i.type_desc ASC  
 --,i.name ASC   
 ) a  
 GROUP BY table_name  
 having MIN(Date_updated) IS NOT NULL  
 order by date;end','@'  
  
--CRIAÇÂO DO CURSOR  
DECLARE DB_Cursor CURSOR FOR  
SELECT Base, Tabela  
FROM ##Principal  
ORDER BY [Update]  
  
--TABELA DE CONTROLE  
DECLARE @Base VARCHAR(8000)  
DECLARE @Tabela VARCHAR(8000)  
DECLARE @Script VARCHAR(8000)  
  
--ABERTURA DO CURSOR E ATRUBUICAO NAS VARIAVEIS  
OPEN DB_Cursor  
FETCH NEXT FROM DB_Cursor INTO @Base, @Tabela  
  
--LACO DE REPETICAO DENTRO DO CURSOR  
WHILE @@FETCH_STATUS=0  
BEGIN  
 SET @Script = 'UPDATE STATISTICS '+@Base+'.dbo.'+@Tabela+' WITH FULLSCAN'  
 IF((SELECT LEFT(CONVERT(VARCHAR, GETDATE(), 108),2))<7)  
  EXEC (@Script)  
 --ANDA COM O CURSOR  
 FETCH NEXT FROM DB_Cursor INTO @base, @Tabela  
END  
--FECHA CURSOR  
CLOSE DB_Cursor  
DEALLOCATE DB_Cursor  
DROP TABLE ##PRINCIPAL  

Vale lembrar que não necessariamente o job não estara executando após as 07:00am, porem caso o horario atual seja maior que 07:00am, nenhuma atualização ira iniciar.

Anúncios
Post a comment or leave a trackback: Trackback URL.

Comentários

  • Leonardo  On 07/11/2011 at 17:16

    Fabrizzio,
    todo dia já roda uma rotina de reindexação dos índices que automaticamente já atualiza as estatísticas. Digamos que de 02:00 até as 10:00 as estatísticas são relevantes, á partir daí já começam a dar inserts, updates, deletes, etc.

    Esse script que você postou me ajudaria? Pelo visto ele é pra ambiente o pau quebra de hora em hora, mesmo na madrugada, onde a galera não tem janela de manutenção. É isso mesmo?

    • fabrizziocaputo  On 07/11/2011 at 17:25

      Leonardo,

      Creio que sim, esse script não fara a reindexação utilizar menos recurso do servidor, para isso voce devera utilizar o Resource Governor do SQL Server 2008.

      Colocando em seu cenario, esse script ficaria algo mais ou menos assim:
      Tabela ultima atualização
      tabela1 13 dias atraz
      tabela2 12 dias atraz
      tabela3 10 dias atraz

      Então, ao se deparar com esses dados, este script ira primeiro atualizar a tabela1, caso o horario atual seja menor que o especificado, no seu caso, 10am, caso ao termino da atualização seja ainda antes das 10, ira partir para a tabela2, porem, a tabela2 terminou de atualizar eram 10:10am, então a proxima tabela de atualização (Quando o job reiniciar as 2am) sera assim:
      tabela3 11 diaas atraz
      tabela1 1 dia atraz
      tabela2 1 dia atraz

      Portanto, a primeira tabela a ser atualizada seria a tabela 3, e não mais a tabela 1.

      Esse script é ideal para ambientes aonde não existe uma tabela bem definida e grande o sulficiente para a atualização de tudo. por exemplo, vamos supor um cenario aonde voce tenha as janelas de manutenção das 5~6am e das 14~17pm, neste caso, este script seria muito bom!

      Qualquer duvida, pode perguntar…

  • Leonardo  On 05/12/2011 at 14:26

    Entendi !!! Blza….obrigado !!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: