Oi! Seja bem-vindo!

Assumindo que temos uma boa indexação de banco de dados, a manutenção de índices fragmentados no SQL Server se torna a cereja do “bolo performance”. 🙂

Por essa razão, hoje vamos aprender as duas principais estratégias, recomendadas pela Microsoft, para fazermos manutenção dos índices de nosso banco de dados SQL Server – com direito a script que gera script automaticamente!

Como fazer a Manutenção de Índices Fragmentados no SQL Server

Embora eu tenha iniciado o artigo falando de uma boa indexação, criei um banco de dados mal definido em termos de índices. Fiz isso para que com poucos INSERTs, possamos aferir desordem no índice criado:

-- Banco de testes
use master
if db_id('curso') is not null 
	drop database curso
go
create database curso
go
use curso
go

-- Tabela de testes com dados aleatórios
if object_id('teste') is not null drop table teste
create table teste (numero int constraint pk_teste primary key nonclustered)
;with cte_seq as (
	select 1 as nr_cont, checksum(newid()) as aleatorio
	union all
	select nr_cont + 1, checksum(newid())
	from cte_seq where nr_cont < 10000)
insert into teste
	select 
		aleatorio
	from cte_seq
	option (maxrecursion 0)
go

 

O script abaixo consulta a fragmentação das tabelas, e como você pode ver, apesar de poucos registros teremos uma grande fragmentação do índice primário:

-- Consultar a fragmentação média:
select 
	nome_tabela = object_name(b.object_id),
	nome_indice = name, 
	fragmentacao_media = avg_fragmentation_in_percent,
	script = case 
		when avg_fragmentation_in_percent > 30 then 'alter index ' + name + ' on ' + object_name(b.object_id) + ' rebuild with (online = on)'
		when avg_fragmentation_in_percent >= 5 and avg_fragmentation_in_percent <= 30 then 'alter index ' + name + ' on ' + object_name(b.object_id) + ' reorganize'
	end
from sys.dm_db_index_physical_stats (db_id('curso'), null, null, null, null) as a -- (Parâmetros da função: banco de dados, tabela, indice, partição física, modo de analise: default, null, limited (limitado), sampled (amostra), detailed (detalhado))
join sys.indexes as b on a.object_id = b.object_id and a.index_id = b.index_id

nome_tabela nome_indice fragmentacao_media
teste pk_teste 96.8750

 

De acordo com a recomendação da Microsoft, as fragmentações devem ser tratadas da seguinte forma:

percentual de fragmentação recomendação
Entre 5% e 30% Reorganizar o índice
Maior que 30% Reconstruir o índice

 

No primeiro teste que fizemos no vídeo, a recomendação foi REBUILD. No segundo REORGANIZE. Para facilitar nossa vida, meu script de análise gera automaticamente o script de manutenção recomendado pela Microsoft.

 

Então aqui vai o script completo da aula de hoje:


------------------------------------------------------------------
-- Defragmentação de indices
------------------------------------------------------------------
--------------------------------------------------
-- Banco de dados para nosso teste
--------------------------------------------------
-- Banco de testes
use master
if db_id('curso') is not null 
	drop database curso
go
create database curso
go
use curso
go

-- Tabela de testes com dados aleatórios
if object_id('teste') is not null drop table teste
create table teste (numero int constraint pk_teste primary key nonclustered)
;with cte_seq as (
	select 1 as nr_cont, checksum(newid()) as aleatorio
	union all
	select nr_cont + 1, checksum(newid())
	from cte_seq where nr_cont < 10000) insert into teste select aleatorio from cte_seq option (maxrecursion 0) go -------------------------------------------------- -- Manutenção de indices -------------------------------------------------- -- Consultar a fragmentação média: select nome_tabela = object_name(b.object_id), nome_indice = name, fragmentacao_media = avg_fragmentation_in_percent, script = case when avg_fragmentation_in_percent > 30 then 'alter index ' + name + ' on ' + object_name(b.object_id) + ' rebuild with (online = on)'
		when avg_fragmentation_in_percent >= 5 and avg_fragmentation_in_percent <= 30 then 'alter index ' + name + ' on ' + object_name(b.object_id) + ' reorganize'
	end
from sys.dm_db_index_physical_stats (db_id('curso'), null, null, null, null) as a -- (Parâmetros da função: banco de dados, tabela, indice, partição física, modo de analise: default, null, limited (limitado), sampled (amostra), detailed (detalhado))
join sys.indexes as b on a.object_id = b.object_id and a.index_id = b.index_id
go
-- Recomendação MS:
-- Entre 5 e 30 = reorganize
-- Maior que 30 = rebuild


-- Desorganizando os dados
insert into teste values (checksum(newid()))
insert into teste values (checksum(newid()))
go


--------------------------------------------------
-- Excluindo dados de teste
--------------------------------------------------
use master
drop database curso


CONCLUSÃO

Naturalmente um banco de dados bem definido não fragmentará freneticamente como o exemplo desse vídeo, que montei dessa forma apenas para podermos simular o funcionamento dos comandos e scripts de manutenção.

Entretanto, não se assuste se você encontrar, no mercado, bancos com definições tão cabeludas quanto essas…. Eu já encontrei, e você com certeza também encontrará…

O ideal, nesses casos extremos, é redefinir as tabelas de banco, certo? Uma pena que quase sempre isso envolve muita gente e muito dinheiro… kkkkk então o jeito é ir mantendo da forma como dá, e as ferramentas que apresentei a você também apoiam nisso.

Abraço do seu amigo Josué 🙂

4 respostas

  1. Seu script é bom. Precisaria altera-lo para que ele pegue o owner da tabela e a tabela, pois se for uma base com vários owners dará erro.

  2. Grande Josué!
    uma das linhas que o script gerou foi essa
    alter index pk_ACESMENU_CHAVE_PRIMARIA on ACESMENU rebuild with (online = on)
    Ao tentar rodar diz que precisa da versão interprise

    Então tentei rodar este comando:
    alter index pk_ACESMENU_CHAVE_PRIMARIA on ACESMENU rebuild

    E mostrado executado com sucesso mas o percentual de fragmentação da tabela continua o mesmo. o que preciso fazer pra atualiza o percentual

    mssql2014

    1. Opa, tudo joia?

      Sim, a opção recompilar mantendo os índices ativos (online=on) só está disponível na versão enterprise… Retirando essa opção o script funcionará.

      É comum o percentual de fragmentação ficar inalterado em tabelas com poucos registros… não sei se esse é seu caso, se for isso não é preciso se preocupar.

      Outra variável que pode ser avaliada é o “fillfactor” do índice, para que fique compatível com os dados armazenados evitando “page splits” de cara na operação de rebuild.

      Espero ter ajudado…

      Abraço,
      Josué

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *