Aqui está um whitepaper sobre quando ocorre a atualização automática de estatísticas . Aqui estão os pontos destacados em relação às atualizações automáticas das estatísticas:
- O tamanho da tabela passou de 0 a> 0 linhas (teste 1).
- O número de linhas na tabela quando as estatísticas foram coletadas era 500 ou menos e o colmodctr da coluna inicial do objeto de estatísticas mudou em mais de 500 desde então (teste 2).
- A tabela tinha mais de 500 linhas quando as estatísticas foram coletadas e o colmodctr da coluna principal do objeto de estatísticas foi alterado em mais de 500 + 20% do número de linhas na tabela quando as estatísticas foram reunidas (teste 3) .
Portanto, o @JNK destacou em um comentário que, se você tiver 1 bilhão de linhas em uma tabela, precisará ter 20.000.5000 gravações na primeira coluna da estatística para acionar uma atualização.
Vamos dar a seguinte estrutura:
CREATE TABLE dbo.test_table (
test_table_id INTEGER IDENTITY(1,1) NOT NULL,
test_table_value VARCHAR(50),
test_table_value2 BIGINT,
test_table_value3 NUMERIC(10,2)
);
CREATE CLUSTERED INDEX cix_test_table ON dbo.test_table (test_table_id, test_table_value);
Agora podemos verificar o que aconteceu nas estatísticas terrestres.
select *
from sys.stats
where object_id = OBJECT_ID('dbo.test_table')
No entanto, para ver se este é um objeto estatístico significativo, precisamos:
dbcc show_statistics('dbo.test_table',cix_test_table)
Portanto, esta estatística não foi atualizada. Isso SELECT
ocorre porque parece que a estatística não é atualizada até que ocorra uma e, mesmo assim, ela SELECT
precisa ficar fora do que o SQL Server possui dentro de seu histograma. Aqui está um script de teste que eu corri para testar isso:
CREATE TABLE test_table (
test_table_id INTEGER IDENTITY(1,1) NOT NULL,
test_table_value VARCHAR(50),
test_table_value2 BIGINT,
test_table_value3 NUMERIC(10,2)
);
CREATE CLUSTERED INDEX cix_test_table ON test_table (test_table_id, test_table_value);
ALTER TABLE test_table ADD CONSTRAINT pk_test_table PRIMARY KEY (test_table_id)
SELECT *
FROM sys.stats
WHERE object_id = OBJECT_ID('dbo.test_table')
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table)
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
declare @test int = 0
WHILE @test < 1
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT 'one row|select < 1', * FROM test_table WHERE test_table_id < 1;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SET @test = 1
WHILE @test < 500
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '100 rows(add 99)|select < 100',* FROM test_table WHERE test_table_id < 100;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--get the table up to 500 rows/changes
WHILE @test < 500
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '500 rows(add 400)|select < 100',* FROM test_table WHERE test_table_id < 100;
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SELECT '500 rows(add 400)|select < 500',* FROM test_table WHERE test_table_id < 500;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 501
SET @test = 500;
WHILE @test < 501
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '501 rows(add 1)|select < 501',* FROM test_table WHERE test_table_id < 501;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 600
SET @test = 501;
WHILE @test < 600
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '600 rows (add 100)|select < 600',* FROM test_table WHERE test_table_id < 600;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 700
SET @test = 600;
WHILE @test < 700
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '700 rows (add 100)|select < 700', * FROM test_table WHERE test_table_id < 700;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 1200
SET @test = 700;
WHILE @test < 1200
BEGIN
INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
SET @test = @test + 1;
END
SELECT '1200 rows (add 500)|select < 1200',* FROM test_table WHERE test_table_id < 1200;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--DROP TABLE test_table
Em vez de desativar cegamente as estatísticas de auto_update, tentaria examinar seu conjunto de dados para distorção. Se os seus dados exibe distorção significativa, então você precisa considerar a criação de estatísticas filtradas e , em seguida, decidir se o gerenciamento de atualizações de estatísticas manualmente é o curso correto de ação.
Para analisar a inclinação, é necessário executar DBCC SHOW_STATISTICS(<stat_object>, <index_name>);
(no script acima sem o WITH STAT_HEADER
) na combinação estatística / índice específica que você deseja examinar. Uma maneira rápida de ocular sua inclinação seria olhar o histograma (terceiro conjunto de resultados) e verificar a variação na sua EQ_ROWS
. Se for razoavelmente consistente, sua inclinação será mínima. Para intensificar, você olha a RANGE_ROWS
coluna e a variação lá, pois isso mede quantas linhas existem entre cada etapa. Por fim, você pode pegar o [All density]
resultado do DENSITY_VECTOR
(segundo conjunto de resultados) e multiplicá-lo pelo [Rows Sampled]
valor no STAT_HEADER
(primeiro conjunto de resultados) e ver qual seria a expectativa média para uma consulta nessa coluna. Você compara essa média com a suaEQ_ROWS
e se houver muitos lugares onde isso varia significativamente, você terá uma inclinação.
Se você achar que tem inclinação, precisará considerar a criação de algumas estatísticas filtradas nos intervalos que possuem alta muito alta, RANGE_ROWS
para que você possa dar etapas adicionais para obter melhores estimativas desses valores.
Depois de ter essas estatísticas filtradas em vigor, você poderá examinar a possibilidade de atualizar as estatísticas manualmente.