Respostas:
Lembre-se do seguinte ao se importar com a atualização de estatísticas (copiada de Reconstruindo índices versus Atualizando estatísticas (Benjamin Nevarez)
Por padrão, a UPDATE STATISTICS
instrução usa apenas uma amostra de registros da tabela. Usar UPDATE STATISTICS WITH FULLSCAN
irá verificar a tabela inteira.
Por padrão, a UPDATE STATISTICS
instrução atualiza as estatísticas do índice e da coluna. O uso da COLUMNS
opção atualizará apenas as estatísticas da coluna. O uso da INDEX
opção atualizará apenas as estatísticas do índice.
A reconstrução de um índice , por exemplo, usando ALTER INDEX … REBUILD
também atualizará as estatísticas do índice com o equivalente a usar WITH FULLSCAN
, a menos que a tabela seja particionada; nesse caso, as estatísticas serão apenas amostradas (se aplica ao SQL Server 2012 e posterior).
As estatísticas criadas manualmente usando CREATE STATISTICS
não são atualizadas por nenhuma ALTER INDEX ... REBUILD
operação, inclusive ALTER TABLE ... REBUILD
. ALTER TABLE ... REBUILD
atualiza estatísticas para o índice em cluster, se um estiver definido na tabela que está sendo reconstruída.
Reorganizar um índice , por exemplo, usar ALTER INDEX … REORGANIZE
não atualiza nenhuma estatística.
A resposta curta é que você precisa usar UPDATE STATISTICS
para atualizar as estatísticas da coluna e que uma reconstrução do índice atualizará apenas as estatísticas do índice. Você pode forçar uma atualização para todas as estatísticas em uma tabela, incluindo estatísticas de índice e estatísticas criadas manualmente, com a UPDATE STATISTICS (tablename) WITH FULLSCAN;
sintaxe.
O código a seguir ilustra as regras encapsuladas acima:
Primeiro, criaremos uma tabela com algumas colunas e um índice em cluster:
USE tempdb;
IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;
CREATE TABLE dbo.SomeTable
(
rn int NOT NULL IDENTITY(1,1)
CONSTRAINT pk
PRIMARY KEY NONCLUSTERED
, i int NOT NULL INDEX i
, d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);
CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);
CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;
INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;
Esta consulta mostra a data em que cada objeto de estatísticas foi atualizado pela última vez:
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Os resultados mostram que ainda não houve atualizações, o que está correto desde que criamos a tabela:
╔═══════════════╦═══════════╦═══════════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═══════════╣ (Dbo.SomeTable, cx, NULL) (Dbo.SomeTable (i) NULL) (Dbo.SomeTable, pk, NULL) (Dbo.SomeTable, d (NULL)) ╚═══════════════╩═══════════╩═══════════╝
Vamos reconstruir a tabela inteira e ver se isso atualiza as estatísticas:
ALTER TABLE dbo.SomeTable REBUILD;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ Para obter mais informações, consulte o artigo: dbo.SomeTable (cx) (Dbo.SomeTable (i) NULL) (Dbo.SomeTable, pk, NULL) (Dbo.SomeTable, d (NULL)) ╚═══════════════╩═══════════╩═════════════════════ ════╝
Os resultados mostram que apenas as estatísticas do índice clusterizado foram atualizadas.
Em seguida, realizamos uma UPDATE STATS
operação discreta :
UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Como você pode ver, acabamos de atualizar as estatísticas na d
coluna:
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ Para obter mais informações, consulte o artigo: dbo.SomeTable (cx) (Dbo.SomeTable (i) NULL) (Dbo.SomeTable, pk, NULL) Para obter mais informações, consulte o artigo: dbo.SomeTable. ╚═══════════════╩═══════════╩═════════════════════ ════╝
Agora, atualizaremos as estatísticas em toda a tabela:
UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ Para obter mais informações, consulte o site do dbo.SomeTable. Para obter mais informações, consulte o artigo: dbo.SomeTable (i) (2018-09-17 14: 09: 13.600) Você pode usar o seguinte comando: dbo.SomeTable (pk) - 2018-09-17 14: 09: 13.603 Para obter mais informações, consulte o artigo: dbo.SomeTable (2018-09-17 14: 09: 13.607) ╚═══════════════╩═══════════╩═════════════════════ ════╝
Como você pode ver, a única maneira de garantir que todas as estatísticas sejam atualizadas é atualizando cada uma manualmente ou com a tabela inteira UPDATE STATISTICS (table);
.
ALTER INDEX ... REBUILD
uma UPDATE STATISTICS
declaração ou de uma . Se a tabela em si for reconstruída, apenas as estatísticas do índice em cluster serão atualizadas. Para sua informação, uma chave primária e um índice em cluster não são necessariamente suportados pelo mesmo objeto de índice.
A página Microsoft Docs para estatísticas do SQL Server afirma :
Operações como reconstruir, desfragmentar ou reorganizar um índice não alteram a distribuição dos dados. Portanto, você não precisa atualizar as estatísticas após executar as operações ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG ou ALTER INDEX REORGANIZE . O Query Optimizer atualiza as estatísticas quando você reconstrói um índice em uma tabela ou exibe com ALTER INDEX REBUILD ou DBCC DBREINDEX, no entanto, esta atualização de estatísticas é um subproduto da recriação do índice. O Query Optimizer não atualiza as estatísticas após as operações DBCC INDEXDEFRAG ou ALTER INDEX REORGANIZE.
REINDEX
atualização das estatísticas da coluna é um efeito colateral da reconstrução do índice - você não precisa atualizar as estatísticas. Os dados na tabela não são alterados. São os mesmos dados, apenas a) mudou sua localização na bandeja giratória (quando uma página é reorganizada) ou b) em uma página diferente (no caso de uma recriação). Assim: a re-index faz (alguns) atualizar estatísticas: não há necessidade de fazê-lo.