Será que um rebuild da tabela actualiza as estatísticas?

Há uns dias surgiu uma questão bem pertinente no seio da minha equipa:

“No fim do processo quero fazer rebuild à tabela, isso actualiza todas as estatísticas também?”

Resposta… aquela famosa “resposta do informático”: Depende.

Resposta do outro lado? Depende do quê?

Resposta: De muita coisa.

Bem, nada como vermos com os nosso olhos. Vamos lá mostrar do que depende.

Como base, para os menos versados no assunto, apenas necessitamos de saber que há vários tipos de estatísticas. Criadas para os nossos índices, criadas por nós e, se AUTO_CREATE_STATISTICS estiver ON, criadas automaticamente pelo SQL Server nas colunas que usamos.

Para garantir que temos as mesmas condições que as do meu teste (e já agora seguir as boas práticas recomendadas)

ALTER DATABASE Demo01 
SET AUTO_CREATE_STATISTICS, AUTO_UPDATE_STATISTICS ON
go

Criamos uma tabelazinha, daquelas que só se criam para este tipo de coisas

create table UpdateStatisticsDemo
(
	id int identity(1,1)
,	col1 int not null
,	col2 int not null
,	col3 varchar(50) not null
,	col4 datetime not null
)
go

E agora criamos 3 novos objectos, um índice clustered, um nonclustered e uma estatística.

create clustered index cidx on UpdateStatisticsDemo (id)
go
create nonclustered index ncidx_col1 on UpdateStatisticsDemo(col1)
go
create statistics Col2Col4 on UpdateStatisticsDemo (Col2, Col4) with fullscan
go

Vamos ver agora as estatísticas que temos criadas nesta tabela

select * from sys.stats
where OBJECT_NAME(object_id) = 'UpdateStatisticsDemo'
Foi a conta que Deus fez.

Como esperado, vemos estatísticas sobre o índice clustered, nonclustered e a estatística criada por nós.

Já agora, vamos ver quando é que foram actualizadas?

SELECT 
		[name]   
        ,	[updated] = STATS_DATE(object_id, stats_id)   
	,	stats_id
	,	auto_created
	,	user_created
FROM sys.stats  
WHERE object_id = OBJECT_ID('UpdateStatisticsDemo'); 

“Nunca” é uma resposta fácil para queijinho. A tabela nem sequer tem dados…

Vamos lá tratar disso.

insert into UpdateStatisticsDemo
	(col1, col2, col3, col4)
select 
	CAST(RAND() * 100000 AS INT)
,	CAST(RAND() * 500000 AS INT)
,	cast(NEWID() as varchar(50))
,	DATEADD(SECOND, ROUND(((DATEDIFF(SECOND, '2019-01-01 08:22:13', '2019-07-14 12:56:31')-1) * RAND()), 0), '2019-01-01 08:22:13')
go 1000

E agora? As estatísticas foram actualizadas?
Sim? Quais? Todas? Alguma?

Parece a mesma imagem, mas não é.

Nenhuma!

E o que acontece se fizermos uma query com predicado numa onde não temos estatísticas?

select id
from UpdateStatisticsDemo
where col3 like '%123%'
3 mais 1 dá 4.

Foi criada uma estatística nova, aquela _WA_Sys_blablablabla. E essa foi actualizada, porque já que o SQL Server varreu a coluna, mais vale aproveitar…

E se fizermos outra query, desta vez sobre uma coluna já com estatística criada?

select id
from UpdateStatisticsDemo
where col2 > 50000
2 a 2 dá empate

Sim, como esperado, já que varreu a coluna, actualizam-se as estatísticas.

Agora vamos à parte do “depende”.

Será que com um REBUILD da tabela todas as estatísticas são actualizadas?

alter table UpdateStatisticsDemo rebuild
Quase!

Quem é que disse “só a estatística sobre o índice clustered e mais nenhuma”? Seria de esperar, pois o índice clustered, afinal, é a tabela.

Mas vejam como nenhuma outra estatística foi actualizada.

Será que um REBUILD a todos os índices o faz?

alter index all on UpdateStatisticsDemo rebuild
2 em 4, não está mal.

Quem é que respondeu “Só aos índices?” (Esta era mais fácil…)

Sem grandes dúvidas, alter index actualiza estatísticas nas colunas que pertencem aos índices.

Agora vamos lá fazer o que falta…

update statistics UpdateStatisticsDemo

Agora sim, todas as nossas estatísticas foram actualizadas.

Resposta à pergunta “no fim do processo quero fazer rebuild à tabela, isso actualiza todas as estatísticas também?” mantém-se a mesma. Depende.

Depende se a tabela acabou de ser criada. Depende de ter um índice clustered. Depende se tem índices nonclustered. Depende se tem já estatísticas criadas pelo SQL Server em outras colunas. Depende se a tabela tem estatísticas criadas por nós.

Mas pelo menos agora já vimos o que precisamos de fazer nesses casos.

Share

You may also like...

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *